Mercurial > libdvdnav.hg
annotate searching.c @ 408:7923e813ec61 src
Make sure part is initialized
part can be left untouched by vm_get_current_title. Having it be
uninitialized and assigned to PTTN_REG would likely be a bad idea.
author | erik |
---|---|
date | Fri, 30 Jul 2010 23:34:13 +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 } |