Mercurial > mplayer.hg
annotate dvdread/dvd_reader.c @ 21055:bc2cf8eb55b3
Move subtitle updating to a separate function, fix inverted condition
which caused timing of DVD subtitles to be ignored so that they were
shown as soon as they were demuxed rather than in their timed position.
author | uau |
---|---|
date | Sun, 19 Nov 2006 17:55:38 +0000 |
parents | 22cb9d5f1e21 |
children | de28f9e8cb00 |
rev | line source |
---|---|
7029 | 1 /* |
15874 | 2 * Copyright (C) 2001, 2002, 2003 Billy Biggs <vektor@dumbterm.net>, |
3 * Håkan Hjort <d95hjort@dtek.chalmers.se>, | |
4 * Björn Englund <d4bjorn@dtek.chalmers.se> | |
7029 | 5 * |
14938
25df9508f9a8
Mark modified files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12431
diff
changeset
|
6 * Modified for use with MPlayer, changes contained in libdvdread_changes.diff. |
18783 | 7 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/ |
14938
25df9508f9a8
Mark modified files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12431
diff
changeset
|
8 * $Id$ |
25df9508f9a8
Mark modified files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12431
diff
changeset
|
9 * |
7029 | 10 * This program is free software; you can redistribute it and/or modify |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or (at | |
13 * your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, but | |
16 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 * General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. | |
23 */ | |
24 | |
7033 | 25 #include "config.h" |
26 | |
7029 | 27 #include <sys/types.h> |
28 #include <sys/stat.h> | |
29 #include <sys/time.h> /* For the timing of dvdcss_title crack. */ | |
30 #include <fcntl.h> | |
31 #include <stdlib.h> | |
32 #include <stdio.h> | |
33 #include <errno.h> | |
34 #include <string.h> | |
35 #include <unistd.h> | |
36 #include <limits.h> | |
37 #include <dirent.h> | |
38 | |
15566 | 39 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__) || defined(__DragonFly__) |
7029 | 40 #define SYS_BSD 1 |
41 #endif | |
42 | |
43 #if defined(__sun) | |
44 #include <sys/mnttab.h> | |
7423
ad967766679a
hpux DVD support fixes by Martin Gansser <mgansser@ngi.de>
arpi
parents:
7358
diff
changeset
|
45 #elif defined(hpux) |
ad967766679a
hpux DVD support fixes by Martin Gansser <mgansser@ngi.de>
arpi
parents:
7358
diff
changeset
|
46 #include </usr/conf/h/mnttab.h> |
7029 | 47 #elif defined(SYS_BSD) |
48 #include <fstab.h> | |
15534 | 49 #elif defined(__linux__) || defined(__CYGWIN__) |
7029 | 50 #include <mntent.h> |
51 #endif | |
52 | |
18910 | 53 #if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION <= 3) && (__MINGW32_MINOR_VERSION < 10) |
10825 | 54 #include <sys/timeb.h> |
55 static void gettimeofday(struct timeval* t,void* timezone){ | |
56 struct timeb timebuffer; | |
57 ftime( &timebuffer ); | |
58 t->tv_sec=timebuffer.time; | |
59 t->tv_usec=1000*timebuffer.millitm; | |
60 } | |
61 #endif | |
62 | |
7029 | 63 #include "dvd_udf.h" |
64 #include "dvd_input.h" | |
65 #include "dvd_reader.h" | |
15874 | 66 #include "md5.h" |
67 | |
68 #define DEFAULT_UDF_CACHE_LEVEL 0 | |
7029 | 69 |
70 struct dvd_reader_s { | |
71 /* Basic information. */ | |
72 int isImageFile; | |
73 | |
74 /* Hack for keeping track of the css status. | |
75 * 0: no css, 1: perhaps (need init of keys), 2: have done init */ | |
76 int css_state; | |
15874 | 77 int css_title; /* Last title that we have called dvdinpute_title for. */ |
7029 | 78 |
79 /* Information required for an image file. */ | |
80 dvd_input_t dev; | |
81 | |
82 /* Information required for a directory path drive. */ | |
83 char *path_root; | |
15874 | 84 |
85 /* Filesystem cache */ | |
86 int udfcache_level; /* 0 - turned off, 1 - on */ | |
87 void *udfcache; | |
7029 | 88 }; |
89 | |
90 struct dvd_file_s { | |
91 /* Basic information. */ | |
92 dvd_reader_t *dvd; | |
93 | |
94 /* Hack for selecting the right css title. */ | |
95 int css_title; | |
96 | |
97 /* Information required for an image file. */ | |
98 uint32_t lb_start; | |
99 uint32_t seek_pos; | |
100 | |
101 /* Information required for a directory path drive. */ | |
102 size_t title_sizes[ 9 ]; | |
103 dvd_input_t title_devs[ 9 ]; | |
104 | |
105 /* Calculated at open-time, size in blocks. */ | |
106 ssize_t filesize; | |
107 }; | |
108 | |
15874 | 109 /** |
110 * Set the level of caching on udf | |
111 * level = 0 (no caching) | |
112 * level = 1 (caching filesystem info) | |
113 */ | |
114 int DVDUDFCacheLevel(dvd_reader_t *device, int level) | |
115 { | |
116 struct dvd_reader_s *dev = (struct dvd_reader_s *)device; | |
117 | |
118 if(level > 0) { | |
119 level = 1; | |
120 } else if(level < 0) { | |
121 return dev->udfcache_level; | |
122 } | |
123 | |
124 dev->udfcache_level = level; | |
125 | |
126 return level; | |
127 } | |
128 | |
129 void *GetUDFCacheHandle(dvd_reader_t *device) | |
130 { | |
131 struct dvd_reader_s *dev = (struct dvd_reader_s *)device; | |
132 | |
133 return dev->udfcache; | |
134 } | |
135 | |
136 void SetUDFCacheHandle(dvd_reader_t *device, void *cache) | |
137 { | |
138 struct dvd_reader_s *dev = (struct dvd_reader_s *)device; | |
139 | |
140 dev->udfcache = cache; | |
141 } | |
142 | |
143 | |
144 | |
7029 | 145 /* Loop over all titles and call dvdcss_title to crack the keys. */ |
146 static int initAllCSSKeys( dvd_reader_t *dvd ) | |
147 { | |
148 struct timeval all_s, all_e; | |
149 struct timeval t_s, t_e; | |
150 char filename[ MAX_UDF_FILE_NAME_LEN ]; | |
151 uint32_t start, len; | |
152 int title; | |
153 | |
15874 | 154 char *nokeys_str = getenv("DVDREAD_NOKEYS"); |
155 if(nokeys_str != NULL) | |
156 return 0; | |
157 | |
7029 | 158 fprintf( stderr, "\n" ); |
159 fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" ); | |
160 fprintf( stderr, "libdvdread: This can take a _long_ time, " | |
161 "please be patient\n\n" ); | |
162 | |
163 gettimeofday(&all_s, NULL); | |
164 | |
165 for( title = 0; title < 100; title++ ) { | |
166 gettimeofday( &t_s, NULL ); | |
167 if( title == 0 ) { | |
168 sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); | |
169 } else { | |
170 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); | |
171 } | |
172 start = UDFFindFile( dvd, filename, &len ); | |
173 if( start != 0 && len != 0 ) { | |
174 /* Perform CSS key cracking for this title. */ | |
175 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", | |
176 filename, start ); | |
15874 | 177 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { |
7029 | 178 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); |
179 } | |
180 gettimeofday( &t_e, NULL ); | |
181 fprintf( stderr, "libdvdread: Elapsed time %ld\n", | |
182 (long int) t_e.tv_sec - t_s.tv_sec ); | |
183 } | |
184 | |
185 if( title == 0 ) continue; | |
186 | |
187 gettimeofday( &t_s, NULL ); | |
188 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 ); | |
189 start = UDFFindFile( dvd, filename, &len ); | |
190 if( start == 0 || len == 0 ) break; | |
191 | |
192 /* Perform CSS key cracking for this title. */ | |
193 fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", | |
194 filename, start ); | |
15874 | 195 if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { |
7029 | 196 fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); |
197 } | |
198 gettimeofday( &t_e, NULL ); | |
199 fprintf( stderr, "libdvdread: Elapsed time %ld\n", | |
200 (long int) t_e.tv_sec - t_s.tv_sec ); | |
201 } | |
202 title--; | |
203 | |
204 fprintf( stderr, "libdvdread: Found %d VTS's\n", title ); | |
205 gettimeofday(&all_e, NULL); | |
206 fprintf( stderr, "libdvdread: Elapsed time %ld\n", | |
207 (long int) all_e.tv_sec - all_s.tv_sec ); | |
208 | |
209 return 0; | |
210 } | |
211 | |
212 | |
213 | |
214 /** | |
215 * Open a DVD image or block device file. | |
216 */ | |
217 static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) | |
218 { | |
219 dvd_reader_t *dvd; | |
220 dvd_input_t dev; | |
221 | |
15874 | 222 dev = dvdinput_open( location ); |
7029 | 223 if( !dev ) { |
224 fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); | |
225 return 0; | |
226 } | |
227 | |
228 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); | |
229 if( !dvd ) return 0; | |
230 dvd->isImageFile = 1; | |
231 dvd->dev = dev; | |
232 dvd->path_root = 0; | |
233 | |
15874 | 234 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; |
235 dvd->udfcache = NULL; | |
236 | |
7029 | 237 if( have_css ) { |
238 /* Only if DVDCSS_METHOD = title, a bit if it's disc or if | |
239 * DVDCSS_METHOD = key but region missmatch. Unfortunaly we | |
240 * don't have that information. */ | |
241 | |
242 dvd->css_state = 1; /* Need key init. */ | |
243 } | |
15874 | 244 dvd->css_title = 0; |
7029 | 245 |
246 return dvd; | |
247 } | |
248 | |
249 static dvd_reader_t *DVDOpenPath( const char *path_root ) | |
250 { | |
251 dvd_reader_t *dvd; | |
252 | |
253 dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); | |
254 if( !dvd ) return 0; | |
255 dvd->isImageFile = 0; | |
256 dvd->dev = 0; | |
257 dvd->path_root = strdup( path_root ); | |
258 | |
15874 | 259 dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; |
260 dvd->udfcache = NULL; | |
261 | |
262 dvd->css_state = 0; /* Only used in the UDF path */ | |
263 dvd->css_title = 0; /* Only matters in the UDF path */ | |
264 | |
7029 | 265 return dvd; |
266 } | |
267 | |
268 #if defined(__sun) | |
269 /* /dev/rdsk/c0t6d0s0 (link to /devices/...) | |
270 /vol/dev/rdsk/c0t6d0/?? | |
271 /vol/rdsk/<name> */ | |
272 static char *sun_block2char( const char *path ) | |
273 { | |
274 char *new_path; | |
275 | |
276 /* Must contain "/dsk/" */ | |
277 if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path ); | |
278 | |
279 /* Replace "/dsk/" with "/rdsk/" */ | |
280 new_path = malloc( strlen(path) + 2 ); | |
281 strcpy( new_path, path ); | |
282 strcpy( strstr( new_path, "/dsk/" ), "" ); | |
283 strcat( new_path, "/rdsk/" ); | |
284 strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) ); | |
285 | |
286 return new_path; | |
287 } | |
288 #endif | |
289 | |
290 #if defined(SYS_BSD) | |
291 /* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recomended to _not_ use r | |
292 OpenBSD /dev/rcd0c, it needs to be the raw device | |
293 NetBSD /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others | |
294 Darwin /dev/rdisk0, it needs to be the raw device | |
295 BSD/OS /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) */ | |
296 static char *bsd_block2char( const char *path ) | |
16510 | 297 #if defined(__FreeBSD__) |
298 { | |
299 return (char *) strdup( path ); | |
300 } | |
301 #else | |
7029 | 302 { |
303 char *new_path; | |
304 | |
305 /* If it doesn't start with "/dev/" or does start with "/dev/r" exit */ | |
10511 | 306 if( strncmp( path, "/dev/", 5 ) || !strncmp( path, "/dev/r", 6 ) ) |
7029 | 307 return (char *) strdup( path ); |
308 | |
309 /* Replace "/dev/" with "/dev/r" */ | |
310 new_path = malloc( strlen(path) + 2 ); | |
311 strcpy( new_path, "/dev/r" ); | |
312 strcat( new_path, path + strlen( "/dev/" ) ); | |
313 | |
314 return new_path; | |
315 } | |
16510 | 316 #endif /* __FreeBSD__ */ |
7029 | 317 #endif |
318 | |
319 dvd_reader_t *DVDOpen( const char *path ) | |
320 { | |
321 struct stat fileinfo; | |
322 int ret, have_css; | |
323 char *dev_name = 0; | |
324 | |
15874 | 325 if( path == NULL ) |
326 return 0; | |
7029 | 327 |
12431
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
328 #ifdef WIN32 |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
329 /* Stat doesn't work on devices under mingwin/cygwin. */ |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
330 if( path[0] && path[1] == ':' && path[2] == '\0' ) |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
331 { |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
332 /* Don't try to stat the file */ |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
333 fileinfo.st_mode = S_IFBLK; |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
334 } |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
335 else |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
336 #endif |
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
337 { |
7029 | 338 ret = stat( path, &fileinfo ); |
339 if( ret < 0 ) { | |
340 /* If we can't stat the file, give up */ | |
341 fprintf( stderr, "libdvdread: Can't stat %s\n", path ); | |
342 perror(""); | |
343 return 0; | |
344 } | |
12431
663fdd72e594
Encrypted dvd playback now accepts -dvd-drive e: on mingw. fix from libdvdread, left out the various cosmetics changes for now
faust3
parents:
10825
diff
changeset
|
345 } |
7029 | 346 |
347 /* Try to open libdvdcss or fall back to standard functions */ | |
15874 | 348 have_css = dvdinput_setup(); |
7029 | 349 |
350 /* First check if this is a block/char device or a file*/ | |
351 if( S_ISBLK( fileinfo.st_mode ) || | |
352 S_ISCHR( fileinfo.st_mode ) || | |
353 S_ISREG( fileinfo.st_mode ) ) { | |
354 | |
355 /** | |
356 * Block devices and regular files are assumed to be DVD-Video images. | |
357 */ | |
358 #if defined(__sun) | |
359 return DVDOpenImageFile( sun_block2char( path ), have_css ); | |
360 #elif defined(SYS_BSD) | |
361 return DVDOpenImageFile( bsd_block2char( path ), have_css ); | |
362 #else | |
363 return DVDOpenImageFile( path, have_css ); | |
364 #endif | |
365 | |
366 } else if( S_ISDIR( fileinfo.st_mode ) ) { | |
367 dvd_reader_t *auth_drive = 0; | |
368 char *path_copy; | |
369 #if defined(SYS_BSD) | |
370 struct fstab* fe; | |
15534 | 371 #elif defined(__sun) || defined(__linux__) || defined(__CYGWIN__) |
7029 | 372 FILE *mntfile; |
373 #endif | |
374 | |
375 /* XXX: We should scream real loud here. */ | |
376 if( !(path_copy = strdup( path ) ) ) return 0; | |
377 | |
378 /* Resolve any symlinks and get the absolut dir name. */ | |
379 { | |
380 char *new_path; | |
381 int cdir = open( ".", O_RDONLY ); | |
382 | |
383 if( cdir >= 0 ) { | |
384 chdir( path_copy ); | |
385 new_path = getcwd( NULL, PATH_MAX ); | |
10443 | 386 #ifndef __MINGW32__ |
7029 | 387 fchdir( cdir ); |
10443 | 388 #endif |
7029 | 389 close( cdir ); |
390 if( new_path ) { | |
391 free( path_copy ); | |
392 path_copy = new_path; | |
393 } | |
394 } | |
395 } | |
396 | |
397 /** | |
398 * If we're being asked to open a directory, check if that directory | |
399 * is the mountpoint for a DVD-ROM which we can use instead. | |
400 */ | |
401 | |
402 if( strlen( path_copy ) > 1 ) { | |
403 if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) | |
404 path_copy[ strlen( path_copy ) - 1 ] = '\0'; | |
405 } | |
406 | |
407 if( strlen( path_copy ) > 9 ) { | |
408 if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), | |
409 "/video_ts" ) ) { | |
410 path_copy[ strlen( path_copy ) - 9 ] = '\0'; | |
411 } | |
412 } | |
413 | |
414 #if defined(SYS_BSD) | |
415 if( ( fe = getfsfile( path_copy ) ) ) { | |
416 dev_name = bsd_block2char( fe->fs_spec ); | |
417 fprintf( stderr, | |
418 "libdvdread: Attempting to use device %s" | |
419 " mounted on %s for CSS authentication\n", | |
420 dev_name, | |
421 fe->fs_file ); | |
422 auth_drive = DVDOpenImageFile( dev_name, have_css ); | |
423 } | |
424 #elif defined(__sun) | |
425 mntfile = fopen( MNTTAB, "r" ); | |
426 if( mntfile ) { | |
427 struct mnttab mp; | |
428 int res; | |
429 | |
430 while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { | |
431 if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { | |
432 dev_name = sun_block2char( mp.mnt_special ); | |
433 fprintf( stderr, | |
434 "libdvdread: Attempting to use device %s" | |
435 " mounted on %s for CSS authentication\n", | |
436 dev_name, | |
437 mp.mnt_mountp ); | |
438 auth_drive = DVDOpenImageFile( dev_name, have_css ); | |
439 break; | |
440 } | |
441 } | |
442 fclose( mntfile ); | |
443 } | |
15534 | 444 #elif defined(__linux__) || defined(__CYGWIN__) |
7029 | 445 mntfile = fopen( MOUNTED, "r" ); |
446 if( mntfile ) { | |
447 struct mntent *me; | |
448 | |
449 while( ( me = getmntent( mntfile ) ) ) { | |
450 if( !strcmp( me->mnt_dir, path_copy ) ) { | |
451 fprintf( stderr, | |
452 "libdvdread: Attempting to use device %s" | |
453 " mounted on %s for CSS authentication\n", | |
454 me->mnt_fsname, | |
455 me->mnt_dir ); | |
456 auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); | |
457 dev_name = strdup(me->mnt_fsname); | |
458 break; | |
459 } | |
460 } | |
461 fclose( mntfile ); | |
462 } | |
15534 | 463 #elif defined(__MINGW32__) |
7033 | 464 dev_name = strdup(path); |
465 auth_drive = DVDOpenImageFile( path, have_css ); | |
7029 | 466 #endif |
467 if( !dev_name ) { | |
468 fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); | |
469 } else if( !auth_drive ) { | |
470 fprintf( stderr, "libdvdread: Device %s inaccessible, " | |
471 "CSS authentication not available.\n", dev_name ); | |
472 } | |
473 | |
474 free( dev_name ); | |
475 free( path_copy ); | |
476 | |
477 /** | |
478 * If we've opened a drive, just use that. | |
479 */ | |
480 if( auth_drive ) return auth_drive; | |
481 | |
482 /** | |
483 * Otherwise, we now try to open the directory tree instead. | |
484 */ | |
485 return DVDOpenPath( path ); | |
486 } | |
487 | |
488 /* If it's none of the above, screw it. */ | |
489 fprintf( stderr, "libdvdread: Could not open %s\n", path ); | |
490 return 0; | |
491 } | |
492 | |
493 void DVDClose( dvd_reader_t *dvd ) | |
494 { | |
495 if( dvd ) { | |
15874 | 496 if( dvd->dev ) dvdinput_close( dvd->dev ); |
7029 | 497 if( dvd->path_root ) free( dvd->path_root ); |
15874 | 498 if( dvd->udfcache ) FreeUDFCache( dvd->udfcache ); |
7029 | 499 free( dvd ); |
500 } | |
501 } | |
502 | |
503 /** | |
504 * Open an unencrypted file on a DVD image file. | |
505 */ | |
506 static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename ) | |
507 { | |
508 uint32_t start, len; | |
509 dvd_file_t *dvd_file; | |
510 | |
511 start = UDFFindFile( dvd, filename, &len ); | |
512 if( !start ) return 0; | |
513 | |
514 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); | |
515 if( !dvd_file ) return 0; | |
516 dvd_file->dvd = dvd; | |
517 dvd_file->lb_start = start; | |
518 dvd_file->seek_pos = 0; | |
519 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); | |
520 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); | |
521 dvd_file->filesize = len / DVD_VIDEO_LB_LEN; | |
522 | |
523 return dvd_file; | |
524 } | |
525 | |
526 /** | |
527 * Searches for <file> in directory <path>, ignoring case. | |
528 * Returns 0 and full filename in <filename>. | |
529 * or -1 on file not found. | |
530 * or -2 on path not found. | |
531 */ | |
532 static int findDirFile( const char *path, const char *file, char *filename ) | |
533 { | |
534 DIR *dir; | |
535 struct dirent *ent; | |
536 | |
537 dir = opendir( path ); | |
538 if( !dir ) return -2; | |
539 | |
540 while( ( ent = readdir( dir ) ) != NULL ) { | |
541 if( !strcasecmp( ent->d_name, file ) ) { | |
542 sprintf( filename, "%s%s%s", path, | |
543 ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), | |
544 ent->d_name ); | |
545 return 0; | |
546 } | |
547 } | |
548 | |
549 return -1; | |
550 } | |
551 | |
552 static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) | |
553 { | |
554 char video_path[ PATH_MAX + 1 ]; | |
555 const char *nodirfile; | |
556 int ret; | |
557 | |
558 /* Strip off the directory for our search */ | |
559 if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) { | |
560 nodirfile = &(file[ 10 ]); | |
561 } else { | |
562 nodirfile = file; | |
563 } | |
564 | |
565 ret = findDirFile( dvd->path_root, nodirfile, filename ); | |
566 if( ret < 0 ) { | |
567 /* Try also with adding the path, just in case. */ | |
568 sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root ); | |
569 ret = findDirFile( video_path, nodirfile, filename ); | |
570 if( ret < 0 ) { | |
571 /* Try with the path, but in lower case. */ | |
572 sprintf( video_path, "%s/video_ts/", dvd->path_root ); | |
573 ret = findDirFile( video_path, nodirfile, filename ); | |
574 if( ret < 0 ) { | |
575 return 0; | |
576 } | |
577 } | |
578 } | |
579 | |
580 return 1; | |
581 } | |
582 | |
583 /** | |
584 * Open an unencrypted file from a DVD directory tree. | |
585 */ | |
586 static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) | |
587 { | |
588 char full_path[ PATH_MAX + 1 ]; | |
589 dvd_file_t *dvd_file; | |
590 struct stat fileinfo; | |
591 dvd_input_t dev; | |
592 | |
593 /* Get the full path of the file. */ | |
594 if( !findDVDFile( dvd, filename, full_path ) ) return 0; | |
595 | |
15874 | 596 dev = dvdinput_open( full_path ); |
7029 | 597 if( !dev ) return 0; |
598 | |
599 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); | |
600 if( !dvd_file ) return 0; | |
601 dvd_file->dvd = dvd; | |
602 dvd_file->lb_start = 0; | |
603 dvd_file->seek_pos = 0; | |
604 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); | |
605 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); | |
606 dvd_file->filesize = 0; | |
607 | |
608 if( stat( full_path, &fileinfo ) < 0 ) { | |
609 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); | |
610 free( dvd_file ); | |
611 return 0; | |
612 } | |
613 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; | |
614 dvd_file->title_devs[ 0 ] = dev; | |
615 dvd_file->filesize = dvd_file->title_sizes[ 0 ]; | |
616 | |
617 return dvd_file; | |
618 } | |
619 | |
620 static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu ) | |
621 { | |
622 char filename[ MAX_UDF_FILE_NAME_LEN ]; | |
623 uint32_t start, len; | |
624 dvd_file_t *dvd_file; | |
625 | |
626 if( title == 0 ) { | |
627 sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); | |
628 } else { | |
629 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); | |
630 } | |
631 start = UDFFindFile( dvd, filename, &len ); | |
632 if( start == 0 ) return 0; | |
633 | |
634 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); | |
635 if( !dvd_file ) return 0; | |
636 dvd_file->dvd = dvd; | |
637 /*Hack*/ dvd_file->css_title = title << 1 | menu; | |
638 dvd_file->lb_start = start; | |
639 dvd_file->seek_pos = 0; | |
640 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); | |
641 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); | |
642 dvd_file->filesize = len / DVD_VIDEO_LB_LEN; | |
643 | |
644 /* Calculate the complete file size for every file in the VOBS */ | |
645 if( !menu ) { | |
646 int cur; | |
647 | |
648 for( cur = 2; cur < 10; cur++ ) { | |
649 sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); | |
650 if( !UDFFindFile( dvd, filename, &len ) ) break; | |
651 dvd_file->filesize += len / DVD_VIDEO_LB_LEN; | |
652 } | |
653 } | |
654 | |
655 if( dvd->css_state == 1 /* Need key init */ ) { | |
7033 | 656 // initAllCSSKeys( dvd ); |
657 // dvd->css_state = 2; | |
7029 | 658 } |
659 /* | |
15874 | 660 if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) { |
7029 | 661 fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n", |
662 filename ); | |
663 } | |
664 */ | |
665 | |
666 return dvd_file; | |
667 } | |
668 | |
669 static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) | |
670 { | |
671 char filename[ MAX_UDF_FILE_NAME_LEN ]; | |
672 char full_path[ PATH_MAX + 1 ]; | |
673 struct stat fileinfo; | |
674 dvd_file_t *dvd_file; | |
675 int i; | |
676 | |
677 dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); | |
678 if( !dvd_file ) return 0; | |
679 dvd_file->dvd = dvd; | |
680 /*Hack*/ dvd_file->css_title = title << 1 | menu; | |
681 dvd_file->lb_start = 0; | |
682 dvd_file->seek_pos = 0; | |
683 memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); | |
684 memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); | |
685 dvd_file->filesize = 0; | |
15874 | 686 |
7029 | 687 if( menu ) { |
688 dvd_input_t dev; | |
689 | |
690 if( title == 0 ) { | |
691 sprintf( filename, "VIDEO_TS.VOB" ); | |
692 } else { | |
693 sprintf( filename, "VTS_%02i_0.VOB", title ); | |
694 } | |
695 if( !findDVDFile( dvd, filename, full_path ) ) { | |
696 free( dvd_file ); | |
697 return 0; | |
698 } | |
699 | |
15874 | 700 dev = dvdinput_open( full_path ); |
7029 | 701 if( dev == NULL ) { |
702 free( dvd_file ); | |
703 return 0; | |
704 } | |
705 | |
706 if( stat( full_path, &fileinfo ) < 0 ) { | |
707 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); | |
708 free( dvd_file ); | |
709 return 0; | |
710 } | |
711 dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; | |
712 dvd_file->title_devs[ 0 ] = dev; | |
15874 | 713 dvdinput_title( dvd_file->title_devs[0], 0); |
7029 | 714 dvd_file->filesize = dvd_file->title_sizes[ 0 ]; |
715 | |
716 } else { | |
717 for( i = 0; i < 9; ++i ) { | |
718 | |
719 sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 ); | |
720 if( !findDVDFile( dvd, filename, full_path ) ) { | |
721 break; | |
722 } | |
723 | |
724 if( stat( full_path, &fileinfo ) < 0 ) { | |
725 fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); | |
726 break; | |
727 } | |
728 | |
729 dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; | |
15874 | 730 dvd_file->title_devs[ i ] = dvdinput_open( full_path ); |
731 dvdinput_title( dvd_file->title_devs[ i ], 0 ); | |
7029 | 732 dvd_file->filesize += dvd_file->title_sizes[ i ]; |
733 } | |
8881
1e40d4a2466f
Function DVDOpenVOBPath only decrypts first VOB file and since each VOB file has
arpi
parents:
7423
diff
changeset
|
734 if( !dvd_file->title_devs[ 0 ] ) { |
7029 | 735 free( dvd_file ); |
736 return 0; | |
737 } | |
738 } | |
739 | |
740 return dvd_file; | |
741 } | |
742 | |
743 dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, | |
744 dvd_read_domain_t domain ) | |
745 { | |
746 char filename[ MAX_UDF_FILE_NAME_LEN ]; | |
15874 | 747 |
748 /* Check arguments. */ | |
749 if( dvd == NULL || titlenum < 0 ) | |
750 return NULL; | |
7029 | 751 |
752 switch( domain ) { | |
753 case DVD_READ_INFO_FILE: | |
754 if( titlenum == 0 ) { | |
755 sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); | |
756 } else { | |
757 sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); | |
758 } | |
759 break; | |
760 case DVD_READ_INFO_BACKUP_FILE: | |
761 if( titlenum == 0 ) { | |
762 sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); | |
763 } else { | |
764 sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); | |
765 } | |
766 break; | |
767 case DVD_READ_MENU_VOBS: | |
768 if( dvd->isImageFile ) { | |
769 return DVDOpenVOBUDF( dvd, titlenum, 1 ); | |
770 } else { | |
771 return DVDOpenVOBPath( dvd, titlenum, 1 ); | |
772 } | |
773 break; | |
774 case DVD_READ_TITLE_VOBS: | |
775 if( titlenum == 0 ) return 0; | |
776 if( dvd->isImageFile ) { | |
777 return DVDOpenVOBUDF( dvd, titlenum, 0 ); | |
778 } else { | |
779 return DVDOpenVOBPath( dvd, titlenum, 0 ); | |
780 } | |
781 break; | |
782 default: | |
783 fprintf( stderr, "libdvdread: Invalid domain for file open.\n" ); | |
15874 | 784 return NULL; |
7029 | 785 } |
786 | |
787 if( dvd->isImageFile ) { | |
788 return DVDOpenFileUDF( dvd, filename ); | |
789 } else { | |
790 return DVDOpenFilePath( dvd, filename ); | |
791 } | |
792 } | |
793 | |
794 void DVDCloseFile( dvd_file_t *dvd_file ) | |
795 { | |
796 int i; | |
797 | |
798 if( dvd_file ) { | |
799 if( dvd_file->dvd->isImageFile ) { | |
800 ; | |
801 } else { | |
802 for( i = 0; i < 9; ++i ) { | |
803 if( dvd_file->title_devs[ i ] ) { | |
15874 | 804 dvdinput_close( dvd_file->title_devs[i] ); |
7029 | 805 } |
806 } | |
807 } | |
808 | |
809 free( dvd_file ); | |
810 dvd_file = 0; | |
811 } | |
812 } | |
813 | |
814 /* Internal, but used from dvd_udf.c */ | |
15874 | 815 int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, |
7029 | 816 size_t block_count, unsigned char *data, |
817 int encrypted ) | |
818 { | |
819 int ret; | |
820 | |
821 if( !device->dev ) { | |
822 fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); | |
823 return 0; | |
824 } | |
825 | |
15874 | 826 ret = dvdinput_seek( device->dev, (int) lb_number ); |
7029 | 827 if( ret != (int) lb_number ) { |
828 fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); | |
829 return 0; | |
830 } | |
831 | |
15874 | 832 return dvdinput_read( device->dev, (char *) data, |
7029 | 833 (int) block_count, encrypted ); |
834 } | |
835 | |
836 /* This is using a single input and starting from 'dvd_file->lb_start' offset. | |
837 * | |
838 * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' | |
839 * into the buffer located at 'data' and if 'encrypted' is set | |
840 * descramble the data if it's encrypted. Returning either an | |
841 * negative error or the number of blocks read. */ | |
842 static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset, | |
843 size_t block_count, unsigned char *data, | |
844 int encrypted ) | |
845 { | |
15874 | 846 return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset, |
847 block_count, data, encrypted ); | |
7029 | 848 } |
849 | |
850 /* This is using possibly several inputs and starting from an offset of '0'. | |
851 * | |
852 * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' | |
853 * into the buffer located at 'data' and if 'encrypted' is set | |
854 * descramble the data if it's encrypted. Returning either an | |
855 * negative error or the number of blocks read. */ | |
856 static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, | |
857 size_t block_count, unsigned char *data, | |
858 int encrypted ) | |
859 { | |
860 int i; | |
861 int ret, ret2, off; | |
862 | |
863 ret = 0; | |
864 ret2 = 0; | |
865 for( i = 0; i < 9; ++i ) { | |
866 if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */ | |
867 | |
868 if( offset < dvd_file->title_sizes[ i ] ) { | |
869 if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { | |
15874 | 870 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); |
7029 | 871 if( off < 0 || off != (int)offset ) { |
872 fprintf( stderr, "libdvdread: Can't seek to block %d\n", | |
873 offset ); | |
874 return off < 0 ? off : 0; | |
875 } | |
15874 | 876 ret = dvdinput_read( dvd_file->title_devs[ i ], data, |
7029 | 877 (int)block_count, encrypted ); |
878 break; | |
879 } else { | |
880 size_t part1_size = dvd_file->title_sizes[ i ] - offset; | |
881 /* FIXME: Really needs to be a while loop. | |
882 * (This is only true if you try and read >1GB at a time) */ | |
883 | |
884 /* Read part 1 */ | |
15874 | 885 off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); |
7029 | 886 if( off < 0 || off != (int)offset ) { |
887 fprintf( stderr, "libdvdread: Can't seek to block %d\n", | |
888 offset ); | |
889 return off < 0 ? off : 0; | |
890 } | |
15874 | 891 ret = dvdinput_read( dvd_file->title_devs[ i ], data, |
7029 | 892 (int)part1_size, encrypted ); |
893 if( ret < 0 ) return ret; | |
894 /* FIXME: This is wrong if i is the last file in the set. | |
895 * also error from this read will not show in ret. */ | |
15874 | 896 |
897 /* Does the next part exist? If not then return now. */ | |
898 if( !dvd_file->title_devs[ i + 1 ] ) return ret; | |
7358
bb40478265df
I experienced several segfaults when trying to play (unencrypted) DVDs
arpi
parents:
7033
diff
changeset
|
899 |
7029 | 900 /* Read part 2 */ |
15874 | 901 off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); |
7029 | 902 if( off < 0 || off != 0 ) { |
903 fprintf( stderr, "libdvdread: Can't seek to block %d\n", | |
904 0 ); | |
905 return off < 0 ? off : 0; | |
906 } | |
15874 | 907 ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ], |
7029 | 908 data + ( part1_size |
909 * (int64_t)DVD_VIDEO_LB_LEN ), | |
910 (int)(block_count - part1_size), | |
911 encrypted ); | |
912 if( ret2 < 0 ) return ret2; | |
913 break; | |
914 } | |
915 } else { | |
916 offset -= dvd_file->title_sizes[ i ]; | |
917 } | |
918 } | |
919 | |
920 return ret + ret2; | |
921 } | |
922 | |
923 /* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. */ | |
924 ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, | |
925 size_t block_count, unsigned char *data ) | |
926 { | |
927 int ret; | |
928 | |
15874 | 929 /* Check arguments. */ |
930 if( dvd_file == NULL || offset < 0 || data == NULL ) | |
931 return -1; | |
932 | |
7029 | 933 /* Hack, and it will still fail for multiple opens in a threaded app ! */ |
934 if( dvd_file->dvd->css_title != dvd_file->css_title ) { | |
935 dvd_file->dvd->css_title = dvd_file->css_title; | |
936 if( dvd_file->dvd->isImageFile ) { | |
15874 | 937 dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start ); |
938 } | |
939 /* Here each vobu has it's own dvdcss handle, so no need to update | |
940 else { | |
941 dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start ); | |
942 }*/ | |
7029 | 943 } |
944 | |
945 if( dvd_file->dvd->isImageFile ) { | |
946 ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset, | |
947 block_count, data, DVDINPUT_READ_DECRYPT ); | |
948 } else { | |
949 ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset, | |
950 block_count, data, DVDINPUT_READ_DECRYPT ); | |
951 } | |
952 | |
953 return (ssize_t)ret; | |
954 } | |
955 | |
10017
535a53c058f8
There are conflicting definitions for DVDFileSeek in the .c and .h file.
diego
parents:
9333
diff
changeset
|
956 int DVDFileSeek( dvd_file_t *dvd_file, int offset ) |
7029 | 957 { |
15874 | 958 /* Check arguments. */ |
959 if( dvd_file == NULL || offset < 0 ) | |
7029 | 960 return -1; |
15874 | 961 |
962 if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) { | |
963 return -1; | |
964 } | |
965 dvd_file->seek_pos = (uint32_t) offset; | |
966 return offset; | |
7029 | 967 } |
968 | |
969 ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) | |
970 { | |
971 unsigned char *secbuf; | |
972 unsigned int numsec, seek_sector, seek_byte; | |
973 int ret; | |
974 | |
15874 | 975 /* Check arguments. */ |
976 if( dvd_file == NULL || data == NULL ) | |
977 return -1; | |
978 | |
7029 | 979 seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN; |
980 seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN; | |
981 | |
15874 | 982 numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + |
983 ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); | |
984 | |
7029 | 985 secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN ); |
986 if( !secbuf ) { | |
987 fprintf( stderr, "libdvdread: Can't allocate memory " | |
988 "for file read!\n" ); | |
989 return 0; | |
990 } | |
991 | |
992 if( dvd_file->dvd->isImageFile ) { | |
993 ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector, | |
994 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); | |
995 } else { | |
996 ret = DVDReadBlocksPath( dvd_file, seek_sector, | |
997 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); | |
998 } | |
999 | |
1000 if( ret != (int) numsec ) { | |
1001 free( secbuf ); | |
1002 return ret < 0 ? ret : 0; | |
1003 } | |
1004 | |
1005 memcpy( data, &(secbuf[ seek_byte ]), byte_size ); | |
1006 free( secbuf ); | |
1007 | |
1008 dvd_file->seek_pos += byte_size; | |
1009 return byte_size; | |
1010 } | |
1011 | |
1012 ssize_t DVDFileSize( dvd_file_t *dvd_file ) | |
1013 { | |
15874 | 1014 /* Check arguments. */ |
1015 if( dvd_file == NULL ) | |
1016 return -1; | |
1017 | |
7029 | 1018 return dvd_file->filesize; |
1019 } | |
15874 | 1020 |
1021 int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid ) | |
1022 { | |
1023 struct md5_ctx ctx; | |
1024 int title; | |
1025 | |
1026 /* Check arguments. */ | |
1027 if( dvd == NULL || discid == NULL ) | |
1028 return 0; | |
1029 | |
1030 /* Go through the first 10 IFO:s, in order, | |
1031 * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ | |
1032 md5_init_ctx( &ctx ); | |
1033 for( title = 0; title < 10; title++ ) { | |
1034 dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); | |
1035 if( dvd_file != NULL ) { | |
1036 ssize_t bytes_read; | |
1037 size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; | |
1038 char *buffer = malloc( file_size ); | |
1039 | |
1040 if( buffer == NULL ) { | |
1041 fprintf( stderr, "libdvdread: DVDDiscId, failed to " | |
1042 "allocate memory for file read!\n" ); | |
1043 return -1; | |
1044 } | |
1045 bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); | |
1046 if( bytes_read != file_size ) { | |
1047 fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes" | |
1048 ", wanted %d\n", bytes_read, file_size ); | |
1049 DVDCloseFile( dvd_file ); | |
1050 return -1; | |
1051 } | |
1052 | |
1053 md5_process_bytes( buffer, file_size, &ctx ); | |
1054 | |
1055 DVDCloseFile( dvd_file ); | |
1056 free( buffer ); | |
1057 } | |
1058 } | |
1059 md5_finish_ctx( &ctx, discid ); | |
1060 | |
1061 return 0; | |
1062 } | |
1063 | |
1064 | |
1065 int DVDISOVolumeInfo( dvd_reader_t *dvd, | |
1066 char *volid, unsigned int volid_size, | |
1067 unsigned char *volsetid, unsigned int volsetid_size ) | |
1068 { | |
1069 unsigned char *buffer; | |
1070 int ret; | |
1071 | |
1072 /* Check arguments. */ | |
1073 if( dvd == NULL ) | |
1074 return 0; | |
1075 | |
1076 if( dvd->dev == NULL ) { | |
1077 /* No block access, so no ISO... */ | |
1078 return -1; | |
1079 } | |
1080 | |
1081 buffer = malloc( DVD_VIDEO_LB_LEN ); | |
1082 if( buffer == NULL ) { | |
1083 fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " | |
1084 "allocate memory for file read!\n" ); | |
1085 return -1; | |
1086 } | |
1087 | |
1088 ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); | |
1089 if( ret != 1 ) { | |
1090 fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " | |
1091 "read ISO9660 Primary Volume Descriptor!\n" ); | |
1092 return -1; | |
1093 } | |
1094 | |
1095 if( (volid != NULL) && (volid_size > 0) ) { | |
1096 unsigned int n; | |
1097 for(n = 0; n < 32; n++) { | |
1098 if(buffer[40+n] == 0x20) { | |
1099 break; | |
1100 } | |
1101 } | |
1102 | |
1103 if(volid_size > n+1) { | |
1104 volid_size = n+1; | |
1105 } | |
1106 | |
1107 memcpy(volid, &buffer[40], volid_size-1); | |
1108 volid[volid_size-1] = '\0'; | |
1109 } | |
1110 | |
1111 if( (volsetid != NULL) && (volsetid_size > 0) ) { | |
1112 if(volsetid_size > 128) { | |
1113 volsetid_size = 128; | |
1114 } | |
1115 memcpy(volsetid, &buffer[190], volsetid_size); | |
1116 } | |
1117 return 0; | |
1118 } | |
1119 | |
1120 | |
1121 int DVDUDFVolumeInfo( dvd_reader_t *dvd, | |
1122 char *volid, unsigned int volid_size, | |
1123 unsigned char *volsetid, unsigned int volsetid_size ) | |
1124 { | |
1125 int ret; | |
1126 /* Check arguments. */ | |
1127 if( dvd == NULL ) | |
1128 return -1; | |
1129 | |
1130 if( dvd->dev == NULL ) { | |
1131 /* No block access, so no UDF VolumeSet Identifier */ | |
1132 return -1; | |
1133 } | |
1134 | |
1135 if( (volid != NULL) && (volid_size > 0) ) { | |
1136 ret = UDFGetVolumeIdentifier(dvd, volid, volid_size); | |
1137 if(!ret) { | |
1138 return -1; | |
1139 } | |
1140 } | |
1141 if( (volsetid != NULL) && (volsetid_size > 0) ) { | |
1142 ret = UDFGetVolumeSetIdentifier(dvd, volsetid, volsetid_size); | |
1143 if(!ret) { | |
1144 return -1; | |
1145 } | |
1146 } | |
1147 | |
1148 return 0; | |
1149 } |