Mercurial > libdvdnav.hg
annotate searching.c @ 314:ba9c3555e92f src
in dvdnav_describe_title_chapters() init *times to NULL, so if something fails we don't leave the ptr uninited
author | nicodvb |
---|---|
date | Thu, 29 Nov 2007 23:09:59 +0000 |
parents | 152e19b2b6a1 |
children | 9abc06e356ff |
rev | line source |
---|---|
131 | 1 /* |
0 | 2 * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> |
3 * | |
4 * This file is part of libdvdnav, a DVD navigation library. | |
5 * | |
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. | |
10 * | |
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. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
19 * | |
20 * $Id$ | |
21 * | |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include "config.h" | |
26 #endif | |
27 | |
114 | 28 #include <assert.h> |
278 | 29 #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
|
30 #include <limits.h> |
288
ce4230602517
moved away from dvdnav_internal.h inclusion of various system headers
nicodvb
parents:
285
diff
changeset
|
31 #include <stdio.h> |
ce4230602517
moved away from dvdnav_internal.h inclusion of various system headers
nicodvb
parents:
285
diff
changeset
|
32 #include <string.h> |
313 | 33 #include <stdlib.h> |
290 | 34 #include <sys/time.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 "dvd_types.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 "nav_types.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 "ifo_types.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
|
38 #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
|
39 #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
|
40 #include "vm/vm.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
|
41 #include "vm/vmcmd.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
|
42 #include "dvdnav.h" |
0 | 43 #include "dvdnav_internal.h" |
44 | |
114 | 45 /* |
46 #define LOG_DEBUG | |
47 */ | |
48 | |
0 | 49 /* Searching API calls */ |
50 | |
24 | 51 /* Scan the ADMAP for a particular block number. */ |
52 /* Return placed in vobu. */ | |
53 /* Returns error status */ | |
114 | 54 /* FIXME: Maybe need to handle seeking outside current cell. */ |
195 | 55 static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_t seekto_block, uint32_t *vobu) { |
24 | 56 vobu_admap_t *admap = NULL; |
114 | 57 |
58 #ifdef LOG_DEBUG | |
59 fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block); | |
60 #endif | |
24 | 61 *vobu = -1; |
62 | |
63 /* Search through the VOBU_ADMAP for the nearest VOBU | |
64 * to the target block */ | |
65 switch(domain) { | |
114 | 66 case FP_DOMAIN: |
67 case VMGM_DOMAIN: | |
68 admap = this->vm->vmgi->menu_vobu_admap; | |
69 break; | |
70 case VTSM_DOMAIN: | |
71 admap = this->vm->vtsi->menu_vobu_admap; | |
72 break; | |
73 case VTS_DOMAIN: | |
74 admap = this->vm->vtsi->vts_vobu_admap; | |
75 break; | |
76 default: | |
77 fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n"); | |
24 | 78 } |
79 if(admap) { | |
166 | 80 uint32_t address = 0; |
81 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
|
82 int admap_entries = (admap->last_byte + 1 - VOBU_ADMAP_SIZE)/VOBU_ADMAP_SIZE; |
24 | 83 |
84 /* Search through ADMAP for best sector */ | |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
85 vobu_start = SRI_END_OF_CELL; |
24 | 86 /* 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
|
87 while(address < admap_entries) { |
24 | 88 next_vobu = admap->vobu_start_sectors[address]; |
89 | |
76 | 90 /* fprintf(MSG_OUT, "libdvdnav: Found block %u\n", next_vobu); */ |
24 | 91 |
305 | 92 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
|
93 break; |
305 | 94 vobu_start = next_vobu; |
95 address++; | |
24 | 96 } |
305 | 97 *vobu = vobu_start; |
98 return DVDNAV_STATUS_OK; | |
24 | 99 } |
76 | 100 fprintf(MSG_OUT, "libdvdnav: admap not located\n"); |
193 | 101 return DVDNAV_STATUS_ERR; |
24 | 102 } |
103 | |
265 | 104 /* FIXME: right now, this function does not use the time tables but interpolates |
105 only the cell times */ | |
106 dvdnav_status_t dvdnav_time_search(dvdnav_t *this, | |
107 uint64_t time) { | |
108 | |
109 uint64_t target = time; | |
110 uint64_t length = 0; | |
111 uint32_t first_cell_nr, last_cell_nr, cell_nr; | |
112 int32_t found; | |
113 cell_playback_t *cell; | |
114 dvd_state_t *state; | |
115 | |
116 if(this->position_current.still != 0) { | |
117 printerr("Cannot seek in a still frame."); | |
118 return DVDNAV_STATUS_ERR; | |
119 } | |
120 | |
121 pthread_mutex_lock(&this->vm_lock); | |
122 state = &(this->vm->state); | |
123 if(!state->pgc) { | |
124 printerr("No current PGC."); | |
125 pthread_mutex_unlock(&this->vm_lock); | |
126 return DVDNAV_STATUS_ERR; | |
127 } | |
128 | |
129 | |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
130 this->cur_cell_time = 0; |
265 | 131 if (this->pgc_based) { |
132 first_cell_nr = 1; | |
133 last_cell_nr = state->pgc->nr_of_cells; | |
134 } else { | |
135 /* Find start cell of program. */ | |
136 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
137 /* Find end cell of program */ | |
138 if(state->pgN < state->pgc->nr_of_programs) | |
139 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
140 else | |
141 last_cell_nr = state->pgc->nr_of_cells; | |
142 } | |
143 | |
144 found = 0; | |
145 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { | |
146 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
|
147 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
|
148 continue; |
265 | 149 length = dvdnav_convert_time(&cell->playback_time); |
150 if (target >= length) { | |
151 target -= length; | |
152 } else { | |
153 /* FIXME: there must be a better way than interpolation */ | |
154 target = target * (cell->last_sector - cell->first_sector + 1) / length; | |
155 target += cell->first_sector; | |
156 | |
157 found = 1; | |
158 break; | |
159 } | |
160 } | |
161 | |
162 if(found) { | |
275
f8ba866996f9
in dvdnav_time_search() vobu and start are uint32_t
nicodvb
parents:
273
diff
changeset
|
163 uint32_t vobu; |
265 | 164 #ifdef LOG_DEBUG |
165 fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", | |
166 cell_nr, first_cell_nr, last_cell_nr); | |
167 #endif | |
168 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
|
169 uint32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; |
265 | 170 |
171 if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { | |
172 #ifdef LOG_DEBUG | |
173 fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , | |
174 state->cellN, state->blockN, target, vobu, start); | |
175 #endif | |
176 this->vm->hop_channel += HOP_SEEK; | |
177 pthread_mutex_unlock(&this->vm_lock); | |
178 return DVDNAV_STATUS_OK; | |
179 } | |
180 } | |
181 } | |
182 | |
183 fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); | |
184 printerr("Error when seeking."); | |
185 pthread_mutex_unlock(&this->vm_lock); | |
186 return DVDNAV_STATUS_ERR; | |
187 } | |
188 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
189 dvdnav_status_t dvdnav_sector_search(dvdnav_t *this, |
195 | 190 uint64_t offset, int32_t origin) { |
0 | 191 uint32_t target = 0; |
192 uint32_t length = 0; | |
114 | 193 uint32_t first_cell_nr, last_cell_nr, cell_nr; |
195 | 194 int32_t found; |
114 | 195 cell_playback_t *cell; |
0 | 196 dvd_state_t *state; |
197 dvdnav_status_t result; | |
198 | |
114 | 199 if(this->position_current.still != 0) { |
200 printerr("Cannot seek in a still frame."); | |
193 | 201 return DVDNAV_STATUS_ERR; |
114 | 202 } |
0 | 203 |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
204 result = dvdnav_get_position(this, &target, &length); |
0 | 205 if(!result) { |
193 | 206 return DVDNAV_STATUS_ERR; |
0 | 207 } |
208 | |
114 | 209 pthread_mutex_lock(&this->vm_lock); |
210 state = &(this->vm->state); | |
211 if(!state->pgc) { | |
212 printerr("No current PGC."); | |
213 pthread_mutex_unlock(&this->vm_lock); | |
193 | 214 return DVDNAV_STATUS_ERR; |
114 | 215 } |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
216 #ifdef LOG_DEBUG |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
217 fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lu pos=%u length=%u\n", offset, target, length); |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
218 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
|
219 #endif |
114 | 220 |
0 | 221 switch(origin) { |
222 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
|
223 if(offset >= length) { |
114 | 224 printerr("Request to seek behind end."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
225 pthread_mutex_unlock(&this->vm_lock); |
193 | 226 return DVDNAV_STATUS_ERR; |
0 | 227 } |
228 target = offset; | |
229 break; | |
230 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
|
231 if(target + offset >= length) { |
114 | 232 printerr("Request to seek behind end."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
233 pthread_mutex_unlock(&this->vm_lock); |
193 | 234 return DVDNAV_STATUS_ERR; |
0 | 235 } |
236 target += offset; | |
237 break; | |
238 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
|
239 if(length < offset) { |
114 | 240 printerr("Request to seek before start."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
241 pthread_mutex_unlock(&this->vm_lock); |
193 | 242 return DVDNAV_STATUS_ERR; |
0 | 243 } |
244 target = length - offset; | |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
245 break; |
0 | 246 default: |
247 /* Error occured */ | |
114 | 248 printerr("Illegal seek mode."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
249 pthread_mutex_unlock(&this->vm_lock); |
193 | 250 return DVDNAV_STATUS_ERR; |
0 | 251 } |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
252 |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
253 this->cur_cell_time = 0; |
132 | 254 if (this->pgc_based) { |
255 first_cell_nr = 1; | |
256 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 257 } else { |
132 | 258 /* Find start cell of program. */ |
259 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
260 /* Find end cell of program */ | |
261 if(state->pgN < state->pgc->nr_of_programs) | |
262 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
263 else | |
264 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 265 } |
132 | 266 |
114 | 267 found = 0; |
0 | 268 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { |
269 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
|
270 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
|
271 continue; |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
272 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
|
273 if (target >= length) { |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
274 target -= length; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
275 } else { |
131 | 276 /* 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
|
277 target += cell->first_sector; |
114 | 278 found = 1; |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
279 break; |
0 | 280 } |
281 } | |
282 | |
114 | 283 if(found) { |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
284 int32_t vobu; |
114 | 285 #ifdef LOG_DEBUG |
76 | 286 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
|
287 cell_nr, first_cell_nr, last_cell_nr); |
114 | 288 #endif |
193 | 289 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
|
290 int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
291 |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
292 if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { |
114 | 293 #ifdef LOG_DEBUG |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
294 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
|
295 state->cellN, state->blockN, target, vobu, start); |
114 | 296 #endif |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
297 this->vm->hop_channel += HOP_SEEK; |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
298 pthread_mutex_unlock(&this->vm_lock); |
193 | 299 return DVDNAV_STATUS_OK; |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
300 } |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
301 } |
0 | 302 } |
114 | 303 |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
304 fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); |
76 | 305 fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target); |
114 | 306 printerr("Error when seeking."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
307 pthread_mutex_unlock(&this->vm_lock); |
193 | 308 return DVDNAV_STATUS_ERR; |
0 | 309 } |
310 | |
195 | 311 dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int32_t part) { |
312 int32_t title, old_part; | |
114 | 313 |
193 | 314 if (dvdnav_current_title_info(this, &title, &old_part) == DVDNAV_STATUS_OK) |
114 | 315 return dvdnav_part_play(this, title, part); |
193 | 316 return DVDNAV_STATUS_ERR; |
0 | 317 } |
318 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
319 dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) { |
114 | 320 pthread_mutex_lock(&this->vm_lock); |
321 if(!this->vm->state.pgc) { | |
322 printerr("No current PGC."); | |
323 pthread_mutex_unlock(&this->vm_lock); | |
193 | 324 return DVDNAV_STATUS_ERR; |
114 | 325 } |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
326 |
114 | 327 #ifdef LOG_DEBUG |
113 | 328 fprintf(MSG_OUT, "libdvdnav: previous chapter\n"); |
114 | 329 #endif |
330 if (!vm_jump_prev_pg(this->vm)) { | |
331 fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n"); | |
332 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
|
333 pthread_mutex_unlock(&this->vm_lock); |
193 | 334 return DVDNAV_STATUS_ERR; |
0 | 335 } |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
336 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
|
337 this->position_current.still = 0; |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
338 this->vm->hop_channel++; |
114 | 339 #ifdef LOG_DEBUG |
76 | 340 fprintf(MSG_OUT, "libdvdnav: previous chapter done\n"); |
114 | 341 #endif |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
342 pthread_mutex_unlock(&this->vm_lock); |
0 | 343 |
193 | 344 return DVDNAV_STATUS_OK; |
0 | 345 } |
346 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
347 dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) { |
114 | 348 pthread_mutex_lock(&this->vm_lock); |
349 if(!this->vm->state.pgc) { | |
350 printerr("No current PGC."); | |
351 pthread_mutex_unlock(&this->vm_lock); | |
193 | 352 return DVDNAV_STATUS_ERR; |
114 | 353 } |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
354 |
114 | 355 #ifdef LOG_DEBUG |
356 fprintf(MSG_OUT, "libdvdnav: top chapter\n"); | |
357 #endif | |
358 if (!vm_jump_top_pg(this->vm)) { | |
359 fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n"); | |
360 printerr("Skip to top chapter failed."); | |
113 | 361 pthread_mutex_unlock(&this->vm_lock); |
193 | 362 return DVDNAV_STATUS_ERR; |
0 | 363 } |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
364 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
|
365 this->position_current.still = 0; |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
366 this->vm->hop_channel++; |
114 | 367 #ifdef LOG_DEBUG |
368 fprintf(MSG_OUT, "libdvdnav: top chapter done\n"); | |
369 #endif | |
370 pthread_mutex_unlock(&this->vm_lock); | |
371 | |
193 | 372 return DVDNAV_STATUS_OK; |
114 | 373 } |
374 | |
375 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
|
376 vm_t *try_vm; |
114 | 377 |
378 pthread_mutex_lock(&this->vm_lock); | |
379 if(!this->vm->state.pgc) { | |
380 printerr("No current PGC."); | |
381 pthread_mutex_unlock(&this->vm_lock); | |
193 | 382 return DVDNAV_STATUS_ERR; |
114 | 383 } |
384 | |
385 #ifdef LOG_DEBUG | |
386 fprintf(MSG_OUT, "libdvdnav: next chapter\n"); | |
387 #endif | |
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
388 /* 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
|
389 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
|
390 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
|
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 /* 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
|
393 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
|
394 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
|
395 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
|
396 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
|
397 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
|
398 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
|
399 pthread_mutex_unlock(&this->vm_lock); |
193 | 400 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
|
401 } |
114 | 402 } |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
403 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
|
404 /* 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
|
405 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
|
406 vm_free_copy(try_vm); |
114 | 407 this->position_current.still = 0; |
408 this->vm->hop_channel++; | |
409 #ifdef LOG_DEBUG | |
76 | 410 fprintf(MSG_OUT, "libdvdnav: next chapter done\n"); |
114 | 411 #endif |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
412 pthread_mutex_unlock(&this->vm_lock); |
0 | 413 |
193 | 414 return DVDNAV_STATUS_OK; |
0 | 415 } |
416 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
417 dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) { |
125 | 418 vm_t *try_vm; |
114 | 419 |
420 pthread_mutex_lock(&this->vm_lock); | |
421 if(!this->vm->state.pgc) { | |
422 printerr("No current PGC."); | |
423 pthread_mutex_unlock(&this->vm_lock); | |
193 | 424 return DVDNAV_STATUS_ERR; |
114 | 425 } |
426 | |
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
427 this->cur_cell_time = 0; |
125 | 428 /* make a copy of current VM and try to navigate the copy to the menu */ |
429 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
|
430 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
|
431 /* Try resume */ |
167 | 432 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
|
433 /* merge changes on success */ |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
434 vm_merge(this->vm, try_vm); |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
435 vm_free_copy(try_vm); |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
436 this->position_current.still = 0; |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
437 this->vm->hop_channel++; |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
438 pthread_mutex_unlock(&this->vm_lock); |
193 | 439 return DVDNAV_STATUS_OK; |
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
440 } |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
441 } |
166 | 442 if (menu == DVD_MENU_Escape) menu = DVD_MENU_Root; |
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
443 |
125 | 444 if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) { |
445 /* merge changes on success */ | |
446 vm_merge(this->vm, try_vm); | |
447 vm_free_copy(try_vm); | |
129 | 448 this->position_current.still = 0; |
114 | 449 this->vm->hop_channel++; |
450 pthread_mutex_unlock(&this->vm_lock); | |
193 | 451 return DVDNAV_STATUS_OK; |
114 | 452 } else { |
125 | 453 vm_free_copy(try_vm); |
454 printerr("No such menu or menu not reachable."); | |
114 | 455 pthread_mutex_unlock(&this->vm_lock); |
193 | 456 return DVDNAV_STATUS_ERR; |
114 | 457 } |
0 | 458 } |
459 | |
195 | 460 dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos, |
461 uint32_t *len) { | |
0 | 462 uint32_t cur_sector; |
195 | 463 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
|
464 cell_playback_t *cell; |
0 | 465 dvd_state_t *state; |
114 | 466 |
467 if(!this->started) { | |
468 printerr("Virtual DVD machine not started."); | |
193 | 469 return DVDNAV_STATUS_ERR; |
114 | 470 } |
471 | |
472 pthread_mutex_lock(&this->vm_lock); | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
473 state = &(this->vm->state); |
224
f19fce15577b
fix assertion failure when someone asks for the position between an Exit
mroi
parents:
195
diff
changeset
|
474 if(!state->pgc || this->vm->stopped) { |
114 | 475 printerr("No current PGC."); |
476 pthread_mutex_unlock(&this->vm_lock); | |
193 | 477 return DVDNAV_STATUS_ERR; |
0 | 478 } |
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
479 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
|
480 this->position_current.domain != state->domain || |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
481 this->position_current.vts != state->vtsN || |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
482 this->position_current.cell_restart != state->cell_restart) { |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
483 printerr("New position not yet determined."); |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
484 pthread_mutex_unlock(&this->vm_lock); |
193 | 485 return DVDNAV_STATUS_ERR; |
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
486 } |
114 | 487 |
0 | 488 /* Get current sector */ |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
489 cur_sector = this->vobu.vobu_start + this->vobu.blockN; |
0 | 490 |
132 | 491 if (this->pgc_based) { |
492 first_cell_nr = 1; | |
493 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 494 } else { |
132 | 495 /* Find start cell of program. */ |
496 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
497 /* Find end cell of program */ | |
498 if(state->pgN < state->pgc->nr_of_programs) | |
499 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
500 else | |
501 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 502 } |
132 | 503 |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
504 *pos = -1; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
505 *len = 0; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
506 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
|
507 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
|
508 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
|
509 /* 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
|
510 * 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
|
511 *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
|
512 } |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
513 *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
|
514 } |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
515 |
166 | 516 assert((signed)*pos != -1); |
0 | 517 |
114 | 518 pthread_mutex_unlock(&this->vm_lock); |
0 | 519 |
193 | 520 return DVDNAV_STATUS_OK; |
0 | 521 } |
522 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
523 dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this, |
195 | 524 uint32_t *pos, |
525 uint32_t *len) { | |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
526 uint32_t cur_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
527 uint32_t first_cell_nr; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
528 uint32_t last_cell_nr; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
529 cell_playback_t *first_cell; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
530 cell_playback_t *last_cell; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
531 dvd_state_t *state; |
114 | 532 |
533 state = &(this->vm->state); | |
534 if(!state->pgc) { | |
535 printerr("No current PGC."); | |
193 | 536 return DVDNAV_STATUS_ERR; |
114 | 537 } |
538 | |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
539 /* Get current sector */ |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
540 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
|
541 |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
542 /* 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
|
543 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
|
544 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
|
545 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
|
546 last_cell = &(state->pgc->cell_playback[last_cell_nr-1]); |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
547 |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
548 *pos = cur_sector - first_cell->first_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
549 *len = last_cell->last_sector - first_cell->first_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
550 |
193 | 551 return DVDNAV_STATUS_OK; |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
552 } |
313 | 553 |
554 uint32_t dvdnav_describe_title_chapters(dvdnav_t *this, int32_t title, uint64_t **times) { | |
555 int32_t retval=0; | |
556 uint16_t parts, i; | |
557 title_info_t *ptitle = NULL; | |
558 ptt_info_t *ptt = NULL; | |
559 ifo_handle_t *ifo; | |
560 pgc_t *pgc; | |
561 cell_playback_t *cell; | |
562 uint64_t length, *tmp=NULL; | |
563 | |
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
|
564 *times = NULL; |
313 | 565 pthread_mutex_lock(&this->vm_lock); |
566 if(!this->vm->vmgi) { | |
567 printerr("Bad VM state or missing VTSI."); | |
568 goto fail; | |
569 } | |
570 if(!this->started) { | |
571 /* don't report an error but be nice */ | |
572 vm_start(this->vm); | |
573 this->started = 1; | |
574 } | |
575 ifo = vm_get_title_ifo(this->vm, title); | |
576 if(!ifo || !ifo->vts_pgcit) { | |
577 printerr("Couldn't open IFO for chosen title, exit."); | |
578 goto fail; | |
579 } | |
580 | |
581 ptitle = &this->vm->vmgi->tt_srpt->title[title-1]; | |
582 parts = ptitle->nr_of_ptts; | |
583 ptt = ifo->vts_ptt_srpt->title[ptitle->vts_ttn-1].ptt; | |
584 | |
585 tmp = calloc(1, sizeof(uint64_t)*parts); | |
586 if(!tmp) | |
587 goto fail; | |
588 | |
589 length = 0; | |
590 for(i=0; i<parts; i++) { | |
591 uint32_t cellnr, endcellnr; | |
592 pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; | |
593 if(ptt[i].pgn > pgc->nr_of_programs) { | |
594 printerr("WRONG part number."); | |
595 goto fail; | |
596 } | |
597 | |
598 cellnr = pgc->program_map[ptt[i].pgn-1]; | |
599 if(ptt[i].pgn < pgc->nr_of_programs) | |
600 endcellnr = pgc->program_map[ptt[i].pgn]; | |
601 else | |
602 endcellnr = 0; | |
603 | |
604 do { | |
605 cell = &pgc->cell_playback[cellnr-1]; | |
606 if(!(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && | |
607 cell->block_mode != BLOCK_MODE_FIRST_CELL | |
608 )) | |
609 { | |
610 tmp[i] = length + dvdnav_convert_time(&cell->playback_time); | |
611 length = tmp[i]; | |
612 } | |
613 cellnr++; | |
614 } while(cellnr < endcellnr); | |
615 } | |
616 vm_ifo_close(ifo); | |
617 retval = parts; | |
618 *times = tmp; | |
619 | |
620 fail: | |
621 pthread_mutex_unlock(&this->vm_lock); | |
622 if(!retval && tmp) | |
623 free(tmp); | |
624 return retval; | |
625 } |