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