Mercurial > libdvdnav.hg
annotate searching.c @ 404:d16ee5945580 src
Prevent display of garbage volume label when the file being scanned is
not a dvd. This is a simple movement of the code that logs the volume
name to after the point that some basic validation of the disc has been
performed.
Patch by John Stebbins of Handbrake
author | nicodvb |
---|---|
date | Tue, 01 Jun 2010 10:01:33 +0000 |
parents | ec2408d48b85 |
children | af0b6a8bf7e9 |
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. */ |
195 | 50 static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_t seekto_block, 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 } |
305 | 92 *vobu = vobu_start; |
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 | |
163 if (dvdnav_scan_admap(this, state->domain, target, &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; |
187 uint32_t length = 0; | |
114 | 188 uint32_t first_cell_nr, last_cell_nr, cell_nr; |
195 | 189 int32_t found; |
114 | 190 cell_playback_t *cell; |
0 | 191 dvd_state_t *state; |
192 dvdnav_status_t result; | |
193 | |
114 | 194 if(this->position_current.still != 0) { |
195 printerr("Cannot seek in a still frame."); | |
193 | 196 return DVDNAV_STATUS_ERR; |
114 | 197 } |
388 | 198 |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
199 result = dvdnav_get_position(this, &target, &length); |
0 | 200 if(!result) { |
193 | 201 return DVDNAV_STATUS_ERR; |
0 | 202 } |
388 | 203 |
114 | 204 pthread_mutex_lock(&this->vm_lock); |
205 state = &(this->vm->state); | |
206 if(!state->pgc) { | |
207 printerr("No current PGC."); | |
208 pthread_mutex_unlock(&this->vm_lock); | |
193 | 209 return DVDNAV_STATUS_ERR; |
114 | 210 } |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
211 #ifdef LOG_DEBUG |
388 | 212 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
|
213 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
|
214 #endif |
114 | 215 |
0 | 216 switch(origin) { |
217 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
|
218 if(offset >= length) { |
114 | 219 printerr("Request to seek behind end."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
220 pthread_mutex_unlock(&this->vm_lock); |
193 | 221 return DVDNAV_STATUS_ERR; |
0 | 222 } |
223 target = offset; | |
224 break; | |
225 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
|
226 if(target + 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_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
|
234 if(length < offset) { |
114 | 235 printerr("Request to seek before start."); |
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 = length - offset; | |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
240 break; |
0 | 241 default: |
242 /* Error occured */ | |
114 | 243 printerr("Illegal seek mode."); |
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 } |
388 | 247 |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
248 this->cur_cell_time = 0; |
132 | 249 if (this->pgc_based) { |
250 first_cell_nr = 1; | |
251 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 252 } else { |
132 | 253 /* Find start cell of program. */ |
254 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
255 /* Find end cell of program */ | |
256 if(state->pgN < state->pgc->nr_of_programs) | |
257 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
258 else | |
259 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 260 } |
132 | 261 |
114 | 262 found = 0; |
0 | 263 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { |
264 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
|
265 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
|
266 continue; |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
267 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
|
268 if (target >= length) { |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
269 target -= length; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
270 } else { |
131 | 271 /* 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
|
272 target += cell->first_sector; |
114 | 273 found = 1; |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
274 break; |
0 | 275 } |
276 } | |
277 | |
114 | 278 if(found) { |
376
430d842f35bd
in dvdnav_sector_search() vobu is uint32_t it; patch by Erik Hovland org
nicodvb
parents:
332
diff
changeset
|
279 uint32_t vobu; |
114 | 280 #ifdef LOG_DEBUG |
76 | 281 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
|
282 cell_nr, first_cell_nr, last_cell_nr); |
114 | 283 #endif |
193 | 284 if (dvdnav_scan_admap(this, state->domain, target, &vobu) == DVDNAV_STATUS_OK) { |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
285 int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; |
388 | 286 |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
287 if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { |
114 | 288 #ifdef LOG_DEBUG |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
289 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
|
290 state->cellN, state->blockN, target, vobu, start); |
114 | 291 #endif |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
292 this->vm->hop_channel += HOP_SEEK; |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
293 pthread_mutex_unlock(&this->vm_lock); |
193 | 294 return DVDNAV_STATUS_OK; |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
295 } |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
296 } |
0 | 297 } |
388 | 298 |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
299 fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); |
388 | 300 fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target); |
114 | 301 printerr("Error when seeking."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
302 pthread_mutex_unlock(&this->vm_lock); |
193 | 303 return DVDNAV_STATUS_ERR; |
0 | 304 } |
305 | |
195 | 306 dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int32_t part) { |
307 int32_t title, old_part; | |
388 | 308 |
193 | 309 if (dvdnav_current_title_info(this, &title, &old_part) == DVDNAV_STATUS_OK) |
114 | 310 return dvdnav_part_play(this, title, part); |
193 | 311 return DVDNAV_STATUS_ERR; |
0 | 312 } |
313 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
314 dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) { |
114 | 315 pthread_mutex_lock(&this->vm_lock); |
316 if(!this->vm->state.pgc) { | |
317 printerr("No current PGC."); | |
318 pthread_mutex_unlock(&this->vm_lock); | |
193 | 319 return DVDNAV_STATUS_ERR; |
114 | 320 } |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
321 |
114 | 322 #ifdef LOG_DEBUG |
113 | 323 fprintf(MSG_OUT, "libdvdnav: previous chapter\n"); |
114 | 324 #endif |
325 if (!vm_jump_prev_pg(this->vm)) { | |
326 fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n"); | |
327 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
|
328 pthread_mutex_unlock(&this->vm_lock); |
193 | 329 return DVDNAV_STATUS_ERR; |
0 | 330 } |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
331 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
|
332 this->position_current.still = 0; |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
333 this->vm->hop_channel++; |
114 | 334 #ifdef LOG_DEBUG |
76 | 335 fprintf(MSG_OUT, "libdvdnav: previous chapter done\n"); |
114 | 336 #endif |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
337 pthread_mutex_unlock(&this->vm_lock); |
0 | 338 |
193 | 339 return DVDNAV_STATUS_OK; |
0 | 340 } |
341 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
342 dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) { |
114 | 343 pthread_mutex_lock(&this->vm_lock); |
344 if(!this->vm->state.pgc) { | |
345 printerr("No current PGC."); | |
346 pthread_mutex_unlock(&this->vm_lock); | |
193 | 347 return DVDNAV_STATUS_ERR; |
114 | 348 } |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
349 |
114 | 350 #ifdef LOG_DEBUG |
351 fprintf(MSG_OUT, "libdvdnav: top chapter\n"); | |
352 #endif | |
353 if (!vm_jump_top_pg(this->vm)) { | |
354 fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n"); | |
355 printerr("Skip to top chapter failed."); | |
113 | 356 pthread_mutex_unlock(&this->vm_lock); |
193 | 357 return DVDNAV_STATUS_ERR; |
0 | 358 } |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
359 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
|
360 this->position_current.still = 0; |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
361 this->vm->hop_channel++; |
114 | 362 #ifdef LOG_DEBUG |
363 fprintf(MSG_OUT, "libdvdnav: top chapter done\n"); | |
364 #endif | |
365 pthread_mutex_unlock(&this->vm_lock); | |
366 | |
193 | 367 return DVDNAV_STATUS_OK; |
114 | 368 } |
369 | |
370 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
|
371 vm_t *try_vm; |
114 | 372 |
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 } |
379 | |
380 #ifdef LOG_DEBUG | |
381 fprintf(MSG_OUT, "libdvdnav: next chapter\n"); | |
382 #endif | |
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
383 /* 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
|
384 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
|
385 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
|
386 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
|
387 /* 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
|
388 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
|
389 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
|
390 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
|
391 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
|
392 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
|
393 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
|
394 pthread_mutex_unlock(&this->vm_lock); |
193 | 395 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
|
396 } |
114 | 397 } |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
398 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
|
399 /* 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
|
400 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
|
401 vm_free_copy(try_vm); |
114 | 402 this->position_current.still = 0; |
403 this->vm->hop_channel++; | |
404 #ifdef LOG_DEBUG | |
76 | 405 fprintf(MSG_OUT, "libdvdnav: next chapter done\n"); |
114 | 406 #endif |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
407 pthread_mutex_unlock(&this->vm_lock); |
0 | 408 |
193 | 409 return DVDNAV_STATUS_OK; |
0 | 410 } |
411 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
412 dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) { |
125 | 413 vm_t *try_vm; |
388 | 414 |
114 | 415 pthread_mutex_lock(&this->vm_lock); |
416 if(!this->vm->state.pgc) { | |
417 printerr("No current PGC."); | |
418 pthread_mutex_unlock(&this->vm_lock); | |
193 | 419 return DVDNAV_STATUS_ERR; |
114 | 420 } |
388 | 421 |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
422 this->cur_cell_time = 0; |
125 | 423 /* make a copy of current VM and try to navigate the copy to the menu */ |
424 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
|
425 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
|
426 /* Try resume */ |
167 | 427 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
|
428 /* merge changes on success */ |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
429 vm_merge(this->vm, try_vm); |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
430 vm_free_copy(try_vm); |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
431 this->position_current.still = 0; |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
432 this->vm->hop_channel++; |
388 | 433 pthread_mutex_unlock(&this->vm_lock); |
193 | 434 return DVDNAV_STATUS_OK; |
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
435 } |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
436 } |
166 | 437 if (menu == DVD_MENU_Escape) menu = DVD_MENU_Root; |
388 | 438 |
125 | 439 if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) { |
440 /* merge changes on success */ | |
441 vm_merge(this->vm, try_vm); | |
442 vm_free_copy(try_vm); | |
129 | 443 this->position_current.still = 0; |
114 | 444 this->vm->hop_channel++; |
388 | 445 pthread_mutex_unlock(&this->vm_lock); |
193 | 446 return DVDNAV_STATUS_OK; |
114 | 447 } else { |
125 | 448 vm_free_copy(try_vm); |
449 printerr("No such menu or menu not reachable."); | |
388 | 450 pthread_mutex_unlock(&this->vm_lock); |
193 | 451 return DVDNAV_STATUS_ERR; |
114 | 452 } |
0 | 453 } |
454 | |
195 | 455 dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos, |
456 uint32_t *len) { | |
0 | 457 uint32_t cur_sector; |
195 | 458 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
|
459 cell_playback_t *cell; |
0 | 460 dvd_state_t *state; |
114 | 461 |
462 if(!this->started) { | |
463 printerr("Virtual DVD machine not started."); | |
193 | 464 return DVDNAV_STATUS_ERR; |
114 | 465 } |
466 | |
467 pthread_mutex_lock(&this->vm_lock); | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
468 state = &(this->vm->state); |
224
f19fce15577b
fix assertion failure when someone asks for the position between an Exit
mroi
parents:
195
diff
changeset
|
469 if(!state->pgc || this->vm->stopped) { |
114 | 470 printerr("No current PGC."); |
471 pthread_mutex_unlock(&this->vm_lock); | |
193 | 472 return DVDNAV_STATUS_ERR; |
0 | 473 } |
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
474 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
|
475 this->position_current.domain != state->domain || |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
476 this->position_current.vts != state->vtsN || |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
477 this->position_current.cell_restart != state->cell_restart) { |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
478 printerr("New position not yet determined."); |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
479 pthread_mutex_unlock(&this->vm_lock); |
193 | 480 return DVDNAV_STATUS_ERR; |
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
481 } |
114 | 482 |
0 | 483 /* Get current sector */ |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
484 cur_sector = this->vobu.vobu_start + this->vobu.blockN; |
0 | 485 |
132 | 486 if (this->pgc_based) { |
487 first_cell_nr = 1; | |
488 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 489 } else { |
132 | 490 /* Find start cell of program. */ |
491 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
492 /* Find end cell of program */ | |
493 if(state->pgN < state->pgc->nr_of_programs) | |
494 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
495 else | |
496 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 497 } |
132 | 498 |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
499 *pos = -1; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
500 *len = 0; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
501 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
|
502 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
|
503 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
|
504 /* 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
|
505 * 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
|
506 *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
|
507 } |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
508 *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
|
509 } |
388 | 510 |
166 | 511 assert((signed)*pos != -1); |
0 | 512 |
114 | 513 pthread_mutex_unlock(&this->vm_lock); |
0 | 514 |
193 | 515 return DVDNAV_STATUS_OK; |
0 | 516 } |
517 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
518 dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this, |
195 | 519 uint32_t *pos, |
520 uint32_t *len) { | |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
521 uint32_t cur_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
522 uint32_t first_cell_nr; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
523 uint32_t last_cell_nr; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
524 cell_playback_t *first_cell; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
525 cell_playback_t *last_cell; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
526 dvd_state_t *state; |
114 | 527 |
528 state = &(this->vm->state); | |
529 if(!state->pgc) { | |
530 printerr("No current PGC."); | |
193 | 531 return DVDNAV_STATUS_ERR; |
114 | 532 } |
533 | |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
534 /* Get current sector */ |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
535 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
|
536 |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
537 /* 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
|
538 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
|
539 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
|
540 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
|
541 last_cell = &(state->pgc->cell_playback[last_cell_nr-1]); |
388 | 542 |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
543 *pos = cur_sector - first_cell->first_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
544 *len = last_cell->last_sector - first_cell->first_sector; |
388 | 545 |
193 | 546 return DVDNAV_STATUS_OK; |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
547 } |
313 | 548 |
315
9abc06e356ff
now dvdnav_describe_title_chapters() also returns the duration of the title
nicodvb
parents:
314
diff
changeset
|
549 uint32_t dvdnav_describe_title_chapters(dvdnav_t *this, int32_t title, uint64_t **times, uint64_t *duration) { |
313 | 550 int32_t retval=0; |
551 uint16_t parts, i; | |
552 title_info_t *ptitle = NULL; | |
553 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
|
554 ifo_handle_t *ifo = NULL; |
313 | 555 pgc_t *pgc; |
556 cell_playback_t *cell; | |
557 uint64_t length, *tmp=NULL; | |
558 | |
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
|
559 *times = NULL; |
315
9abc06e356ff
now dvdnav_describe_title_chapters() also returns the duration of the title
nicodvb
parents:
314
diff
changeset
|
560 *duration = 0; |
313 | 561 pthread_mutex_lock(&this->vm_lock); |
562 if(!this->vm->vmgi) { | |
563 printerr("Bad VM state or missing VTSI."); | |
564 goto fail; | |
565 } | |
566 if(!this->started) { | |
567 /* don't report an error but be nice */ | |
568 vm_start(this->vm); | |
569 this->started = 1; | |
570 } | |
571 ifo = vm_get_title_ifo(this->vm, title); | |
572 if(!ifo || !ifo->vts_pgcit) { | |
573 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
|
574 retval = 0; |
313 | 575 goto fail; |
576 } | |
388 | 577 |
313 | 578 ptitle = &this->vm->vmgi->tt_srpt->title[title-1]; |
579 parts = ptitle->nr_of_ptts; | |
580 ptt = ifo->vts_ptt_srpt->title[ptitle->vts_ttn-1].ptt; | |
388 | 581 |
313 | 582 tmp = calloc(1, sizeof(uint64_t)*parts); |
583 if(!tmp) | |
584 goto fail; | |
388 | 585 |
313 | 586 length = 0; |
587 for(i=0; i<parts; i++) { | |
588 uint32_t cellnr, endcellnr; | |
589 pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; | |
590 if(ptt[i].pgn > pgc->nr_of_programs) { | |
591 printerr("WRONG part number."); | |
592 goto fail; | |
593 } | |
388 | 594 |
313 | 595 cellnr = pgc->program_map[ptt[i].pgn-1]; |
596 if(ptt[i].pgn < pgc->nr_of_programs) | |
597 endcellnr = pgc->program_map[ptt[i].pgn]; | |
598 else | |
599 endcellnr = 0; | |
388 | 600 |
313 | 601 do { |
602 cell = &pgc->cell_playback[cellnr-1]; | |
603 if(!(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && | |
604 cell->block_mode != BLOCK_MODE_FIRST_CELL | |
605 )) | |
606 { | |
607 tmp[i] = length + dvdnav_convert_time(&cell->playback_time); | |
608 length = tmp[i]; | |
609 } | |
610 cellnr++; | |
611 } while(cellnr < endcellnr); | |
612 } | |
315
9abc06e356ff
now dvdnav_describe_title_chapters() also returns the duration of the title
nicodvb
parents:
314
diff
changeset
|
613 *duration = length; |
313 | 614 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
|
615 ifo = NULL; |
313 | 616 retval = parts; |
617 *times = tmp; | |
618 | |
619 fail: | |
620 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
|
621 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
|
622 vm_ifo_close(ifo); |
313 | 623 if(!retval && tmp) |
624 free(tmp); | |
625 return retval; | |
626 } |