[Mplayer-cvslog] CVS: main/libmpdvdkit2 bswap.h,NONE,1.1 dvd_input.c,NONE,1.1 dvd_input.h,NONE,1.1 dvd_reader.c,NONE,1.1 dvd_reader.h,NONE,1.1 dvd_udf.c,NONE,1.1 dvd_udf.h,NONE,1.1 ifo_print.c,NONE,1.1 ifo_print.h,NONE,1.1 ifo_read.c,NONE,1.1 ifo_read.h,NONE,1.1 ifo_types.h,NONE,1.1 nav_print.c,NONE,1.1 nav_print.h,NONE,1.1 nav_read.c,NONE,1.1 nav_read.h,NONE,1.1 nav_types.h,NONE,1.1
Arpi of Ize
arpi at mplayerhq.hu
Sat Aug 17 00:37:51 CEST 2002
Update of /cvsroot/mplayer/main/libmpdvdkit2
In directory mail:/var/tmp.root/cvs-serv17341
Added Files:
bswap.h dvd_input.c dvd_input.h dvd_reader.c dvd_reader.h
dvd_udf.c dvd_udf.h ifo_print.c ifo_print.h ifo_read.c
ifo_read.h ifo_types.h nav_print.c nav_print.h nav_read.c
nav_read.h nav_types.h
Log Message:
importing libdvdread 0.9.3 files
--- NEW FILE ---
#ifndef BSWAP_H_INCLUDED
#define BSWAP_H_INCLUDED
/*
* Copyright (C) 2000, 2001 Billy Biggs <vektor at dumbterm.net>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <config.h>
#if defined(WORDS_BIGENDIAN)
/* All bigendian systems are fine, just ignore the swaps. */
#define B2N_16(x) (void)(x)
#define B2N_32(x) (void)(x)
#define B2N_64(x) (void)(x)
#else
#if defined(__linux__)
#include <byteswap.h>
#define B2N_16(x) x = bswap_16(x)
#define B2N_32(x) x = bswap_32(x)
#define B2N_64(x) x = bswap_64(x)
#elif defined(__NetBSD__)
#include <sys/endian.h>
#define B2N_16(x) BE16TOH(x)
#define B2N_32(x) BE32TOH(x)
#define B2N_64(x) BE64TOH(x)
#elif defined(__OpenBSD__)
#include <sys/endian.h>
#define B2N_16(x) x = swap16(x)
#define B2N_32(x) x = swap32(x)
#define B2N_64(x) x = swap64(x)
/* This is a slow but portable implementation, it has multiple evaluation
* problems so beware.
* FreeBSD and Solaris don't have <byteswap.h> or any other such
* functionality!
*/
#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__)
#define B2N_16(x) \
x = ((((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8))
#define B2N_32(x) \
x = ((((x) & 0xff000000) >> 24) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x000000ff) << 24))
#define B2N_64(x) \
x = ((((x) & 0xff00000000000000) >> 56) | \
(((x) & 0x00ff000000000000) >> 40) | \
(((x) & 0x0000ff0000000000) >> 24) | \
(((x) & 0x000000ff00000000) >> 8) | \
(((x) & 0x00000000ff000000) << 8) | \
(((x) & 0x0000000000ff0000) << 24) | \
(((x) & 0x000000000000ff00) << 40) | \
(((x) & 0x00000000000000ff) << 56))
#else
/* If there isn't a header provided with your system with this functionality
* add the relevant || define( ) to the portable implementation above.
*/
#error "You need to add endian swap macros for you're system"
#endif
#endif /* WORDS_BIGENDIAN */
#endif /* BSWAP_H_INCLUDED */
--- NEW FILE ---
/*
* Copyright (C) 2002 Samuel Hocevar <sam at zoy.org>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <dlfcn.h>
#include "dvd_reader.h"
#include "dvd_input.h"
/* For libdvdcss */
typedef struct dvdcss_s *dvdcss_handle;
dvdcss_handle (*DVDcss_open) (const char *);
int (*DVDcss_close) (dvdcss_handle);
int (*DVDcss_seek) (dvdcss_handle, int, int);
int (*DVDcss_title) (dvdcss_handle, int);
int (*DVDcss_read) (dvdcss_handle, void *, int, int);
char * (*DVDcss_error) (dvdcss_handle);
/* The DVDinput handle, add stuff here for new input methods. */
struct dvd_input_s {
/* libdvdcss handle */
dvdcss_handle dvdcss;
/* dummy file input */
int fd;
};
/**
* initialize and open a DVD device or file.
*/
static dvd_input_t css_open(const char *target)
{
dvd_input_t dev;
/* Allocate the handle structure */
dev = (dvd_input_t) malloc(sizeof(dvd_input_t));
if(dev == NULL) {
fprintf(stderr, "libdvdread: Could not allocate memory.\n");
return NULL;
}
/* Really open it with libdvdcss */
dev->dvdcss = DVDcss_open(target);
if(dev->dvdcss == 0) {
fprintf(stderr, "libdvdread: Could not open device with libdvdcss.\n");
free(dev);
return NULL;
}
return dev;
}
/**
* return the last error message
*/
static char *css_error(dvd_input_t dev)
{
return DVDcss_error(dev->dvdcss);
}
/**
* seek into the device.
*/
static int css_seek(dvd_input_t dev, int blocks, int flags)
{
return DVDcss_seek(dev->dvdcss, blocks, flags);
}
/**
* set the block for the begining of a new title (key).
*/
static int css_title(dvd_input_t dev, int block)
{
return DVDcss_title(dev->dvdcss, block);
}
/**
* read data from the device.
*/
static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags)
{
return DVDcss_read(dev->dvdcss, buffer, blocks, flags);
}
/**
* close the DVD device and clean up the library.
*/
static int css_close(dvd_input_t dev)
{
int ret;
ret = DVDcss_close(dev->dvdcss);
if(ret < 0)
return ret;
free(dev);
return 0;
}
/**
* initialize and open a DVD device or file.
*/
static dvd_input_t file_open(const char *target)
{
dvd_input_t dev;
/* Allocate the library structure */
dev = (dvd_input_t) malloc(sizeof(dvd_input_t));
if(dev == NULL) {
fprintf(stderr, "libdvdread: Could not allocate memory.\n");
return NULL;
}
/* Open the device */
dev->fd = open(target, O_RDONLY);
if(dev->fd < 0) {
perror("libdvdread: Could not open input");
free(dev);
return NULL;
}
return dev;
}
/**
* return the last error message
*/
static char *file_error(dvd_input_t dev)
{
/* use strerror(errno)? */
return "unknown error";
}
/**
* seek into the device.
*/
static int file_seek(dvd_input_t dev, int blocks, int flags)
{
off_t pos;
pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET);
if(pos < 0) {
return pos;
}
/* assert pos % DVD_VIDEO_LB_LEN == 0 */
return (int) (pos / DVD_VIDEO_LB_LEN);
}
/**
* set the block for the begining of a new title (key).
*/
static int file_title(dvd_input_t dev, int block)
{
return -1;
}
/**
* read data from the device.
*/
static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags)
{
size_t len;
ssize_t ret;
len = (size_t)blocks * DVD_VIDEO_LB_LEN;
while(len > 0) {
ret = read(dev->fd, buffer, len);
if(ret < 0) {
/* One of the reads failed, too bad. We won't even bother
* returning the reads that went ok, and as in the posix spec
* the file postition is left unspecified after a failure. */
return ret;
}
if(ret == 0) {
/* Nothing more to read. Return the whole blocks, if any, that we got.
and adjust the file possition back to the previous block boundary. */
size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len;
off_t over_read = -(bytes % DVD_VIDEO_LB_LEN);
/*off_t pos =*/ lseek(dev->fd, over_read, SEEK_CUR);
/* should have pos % 2048 == 0 */
return (int) (bytes / DVD_VIDEO_LB_LEN);
}
len -= ret;
}
return blocks;
}
/**
* close the DVD device and clean up.
*/
static int file_close(dvd_input_t dev)
{
int ret;
ret = close(dev->fd);
if(ret < 0)
return ret;
free(dev);
return 0;
}
/**
* Setup read functions with either libdvdcss or minimal DVD access.
*/
int DVDInputSetup(void)
{
void *dvdcss_library = NULL;
char **dvdcss_version = NULL;
dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY);
if(dvdcss_library != NULL) {
#if defined(__OpenBSD__) && !defined(__ELF__)
#define U_S "_"
#else
#define U_S
#endif
DVDcss_open = (dvdcss_handle (*)(const char*))
dlsym(dvdcss_library, U_S "dvdcss_open");
DVDcss_close = (int (*)(dvdcss_handle))
dlsym(dvdcss_library, U_S "dvdcss_close");
DVDcss_title = (int (*)(dvdcss_handle, int))
dlsym(dvdcss_library, U_S "dvdcss_title");
DVDcss_seek = (int (*)(dvdcss_handle, int, int))
dlsym(dvdcss_library, U_S "dvdcss_seek");
DVDcss_read = (int (*)(dvdcss_handle, void*, int, int))
dlsym(dvdcss_library, U_S "dvdcss_read");
DVDcss_error = (char* (*)(dvdcss_handle))
dlsym(dvdcss_library, U_S "dvdcss_error");
dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2");
if(dlsym(dvdcss_library, U_S "dvdcss_crack")) {
fprintf(stderr,
"libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n"
"libdvdread: You should get the latest version from "
"http://www.videolan.org/\n" );
dlclose(dvdcss_library);
dvdcss_library = NULL;
} else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek
|| !DVDcss_read || !DVDcss_error || !dvdcss_version) {
fprintf(stderr, "libdvdread: Missing symbols in libdvdcss.so.2, "
"this shouldn't happen !\n");
dlclose(dvdcss_library);
}
}
if(dvdcss_library != NULL) {
/*
char *psz_method = getenv( "DVDCSS_METHOD" );
char *psz_verbose = getenv( "DVDCSS_VERBOSE" );
fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method);
fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose);
*/
fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n",
*dvdcss_version);
/* libdvdcss wraper functions */
DVDinput_open = css_open;
DVDinput_close = css_close;
DVDinput_seek = css_seek;
DVDinput_title = css_title;
DVDinput_read = css_read;
DVDinput_error = css_error;
return 1;
} else {
fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n");
/* libdvdcss replacement functions */
DVDinput_open = file_open;
DVDinput_close = file_close;
DVDinput_seek = file_seek;
DVDinput_title = file_title;
DVDinput_read = file_read;
DVDinput_error = file_error;
return 0;
}
}
--- NEW FILE ---
#ifndef DVD_INPUT_H_INCLUDED
#define DVD_INPUT_H_INCLUDED
/*
* Copyright (C) 2001, 2002 Samuel Hocevar <sam at zoy.org>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
/**
* Defines and flags. Make sure they fit the libdvdcss API!
*/
#define DVDINPUT_NOFLAGS 0
#define DVDINPUT_READ_DECRYPT (1 << 0)
#define DVDINPUT_SEEK_MPEG (1 << 0)
#define DVDINPUT_SEEK_KEY (1 << 1)
typedef struct dvd_input_s *dvd_input_t;
/**
* Pointers which will be filled either the input meathods functions.
*/
dvd_input_t (*DVDinput_open) (const char *);
int (*DVDinput_close) (dvd_input_t);
int (*DVDinput_seek) (dvd_input_t, int, int);
int (*DVDinput_title) (dvd_input_t, int);
int (*DVDinput_read) (dvd_input_t, void *, int, int);
char * (*DVDinput_error) (dvd_input_t);
/**
* Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support.
*/
int DVDInputSetup(void);
#endif /* DVD_INPUT_H_INCLUDED */
--- NEW FILE ---
/*
* Copyright (C) 2001, 2002 Billy Biggs <vektor at dumbterm.net>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h> /* For the timing of dvdcss_title crack. */
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__)
#define SYS_BSD 1
#endif
#if defined(__sun)
#include <sys/mnttab.h>
#elif defined(SYS_BSD)
#include <fstab.h>
#elif defined(__linux__)
#include <mntent.h>
#endif
#include "dvd_udf.h"
#include "dvd_input.h"
#include "dvd_reader.h"
struct dvd_reader_s {
/* Basic information. */
int isImageFile;
/* Hack for keeping track of the css status.
* 0: no css, 1: perhaps (need init of keys), 2: have done init */
int css_state;
int css_title; /* Last title that we have called DVDinpute_title for. */
/* Information required for an image file. */
dvd_input_t dev;
/* Information required for a directory path drive. */
char *path_root;
};
struct dvd_file_s {
/* Basic information. */
dvd_reader_t *dvd;
/* Hack for selecting the right css title. */
int css_title;
/* Information required for an image file. */
uint32_t lb_start;
uint32_t seek_pos;
/* Information required for a directory path drive. */
size_t title_sizes[ 9 ];
dvd_input_t title_devs[ 9 ];
/* Calculated at open-time, size in blocks. */
ssize_t filesize;
};
/* Loop over all titles and call dvdcss_title to crack the keys. */
static int initAllCSSKeys( dvd_reader_t *dvd )
{
struct timeval all_s, all_e;
struct timeval t_s, t_e;
char filename[ MAX_UDF_FILE_NAME_LEN ];
uint32_t start, len;
int title;
fprintf( stderr, "\n" );
fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" );
fprintf( stderr, "libdvdread: This can take a _long_ time, "
"please be patient\n\n" );
gettimeofday(&all_s, NULL);
for( title = 0; title < 100; title++ ) {
gettimeofday( &t_s, NULL );
if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
}
start = UDFFindFile( dvd, filename, &len );
if( start != 0 && len != 0 ) {
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( DVDinput_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start);
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) t_e.tv_sec - t_s.tv_sec );
}
if( title == 0 ) continue;
gettimeofday( &t_s, NULL );
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
start = UDFFindFile( dvd, filename, &len );
if( start == 0 || len == 0 ) break;
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( DVDinput_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start);
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) t_e.tv_sec - t_s.tv_sec );
}
title--;
fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
gettimeofday(&all_e, NULL);
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) all_e.tv_sec - all_s.tv_sec );
return 0;
}
/**
* Open a DVD image or block device file.
*/
static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
{
dvd_reader_t *dvd;
dvd_input_t dev;
dev = DVDinput_open( location );
if( !dev ) {
fprintf( stderr, "libdvdread: Can't open %s for reading\n", location );
return 0;
}
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 1;
dvd->dev = dev;
dvd->path_root = 0;
if( have_css ) {
/* Only if DVDCSS_METHOD = title, a bit if it's disc or if
* DVDCSS_METHOD = key but region missmatch. Unfortunaly we
* don't have that information. */
dvd->css_state = 1; /* Need key init. */
}
return dvd;
}
static dvd_reader_t *DVDOpenPath( const char *path_root )
{
dvd_reader_t *dvd;
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 0;
dvd->dev = 0;
dvd->path_root = strdup( path_root );
return dvd;
}
#if defined(__sun)
/* /dev/rdsk/c0t6d0s0 (link to /devices/...)
/vol/dev/rdsk/c0t6d0/??
/vol/rdsk/<name> */
static char *sun_block2char( const char *path )
{
char *new_path;
/* Must contain "/dsk/" */
if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
/* Replace "/dsk/" with "/rdsk/" */
new_path = malloc( strlen(path) + 2 );
strcpy( new_path, path );
strcpy( strstr( new_path, "/dsk/" ), "" );
strcat( new_path, "/rdsk/" );
strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) );
return new_path;
}
#endif
#if defined(SYS_BSD)
/* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recomended to _not_ use r
OpenBSD /dev/rcd0c, it needs to be the raw device
NetBSD /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others
Darwin /dev/rdisk0, it needs to be the raw device
BSD/OS /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) */
static char *bsd_block2char( const char *path )
{
char *new_path;
/* If it doesn't start with "/dev/" or does start with "/dev/r" exit */
if( !strncmp( path, "/dev/", 5 ) || strncmp( path, "/dev/r", 6 ) )
return (char *) strdup( path );
/* Replace "/dev/" with "/dev/r" */
new_path = malloc( strlen(path) + 2 );
strcpy( new_path, "/dev/r" );
strcat( new_path, path + strlen( "/dev/" ) );
return new_path;
}
#endif
dvd_reader_t *DVDOpen( const char *path )
{
struct stat fileinfo;
int ret, have_css;
char *dev_name = 0;
if( !path ) return 0;
ret = stat( path, &fileinfo );
if( ret < 0 ) {
/* If we can't stat the file, give up */
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
perror("");
return 0;
}
/* Try to open libdvdcss or fall back to standard functions */
have_css = DVDInputSetup();
/* First check if this is a block/char device or a file*/
if( S_ISBLK( fileinfo.st_mode ) ||
S_ISCHR( fileinfo.st_mode ) ||
S_ISREG( fileinfo.st_mode ) ) {
/**
* Block devices and regular files are assumed to be DVD-Video images.
*/
#if defined(__sun)
return DVDOpenImageFile( sun_block2char( path ), have_css );
#elif defined(SYS_BSD)
return DVDOpenImageFile( bsd_block2char( path ), have_css );
#else
return DVDOpenImageFile( path, have_css );
#endif
} else if( S_ISDIR( fileinfo.st_mode ) ) {
dvd_reader_t *auth_drive = 0;
char *path_copy;
#if defined(SYS_BSD)
struct fstab* fe;
#elif defined(__sun) || defined(__linux__)
FILE *mntfile;
#endif
/* XXX: We should scream real loud here. */
if( !(path_copy = strdup( path ) ) ) return 0;
/* Resolve any symlinks and get the absolut dir name. */
{
char *new_path;
int cdir = open( ".", O_RDONLY );
if( cdir >= 0 ) {
chdir( path_copy );
new_path = getcwd( NULL, PATH_MAX );
fchdir( cdir );
close( cdir );
if( new_path ) {
free( path_copy );
path_copy = new_path;
}
}
}
/**
* If we're being asked to open a directory, check if that directory
* is the mountpoint for a DVD-ROM which we can use instead.
*/
if( strlen( path_copy ) > 1 ) {
if( path_copy[ strlen( path_copy ) - 1 ] == '/' )
path_copy[ strlen( path_copy ) - 1 ] = '\0';
}
if( strlen( path_copy ) > 9 ) {
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
"/video_ts" ) ) {
path_copy[ strlen( path_copy ) - 9 ] = '\0';
}
}
#if defined(SYS_BSD)
if( ( fe = getfsfile( path_copy ) ) ) {
dev_name = bsd_block2char( fe->fs_spec );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
fe->fs_file );
auth_drive = DVDOpenImageFile( dev_name, have_css );
}
#elif defined(__sun)
mntfile = fopen( MNTTAB, "r" );
if( mntfile ) {
struct mnttab mp;
int res;
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
dev_name = sun_block2char( mp.mnt_special );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
mp.mnt_mountp );
auth_drive = DVDOpenImageFile( dev_name, have_css );
break;
}
}
fclose( mntfile );
}
#elif defined(__linux__)
mntfile = fopen( MOUNTED, "r" );
if( mntfile ) {
struct mntent *me;
while( ( me = getmntent( mntfile ) ) ) {
if( !strcmp( me->mnt_dir, path_copy ) ) {
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
me->mnt_fsname,
me->mnt_dir );
auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css );
dev_name = strdup(me->mnt_fsname);
break;
}
}
fclose( mntfile );
}
#endif
if( !dev_name ) {
fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
} else if( !auth_drive ) {
fprintf( stderr, "libdvdread: Device %s inaccessible, "
"CSS authentication not available.\n", dev_name );
}
free( dev_name );
free( path_copy );
/**
* If we've opened a drive, just use that.
*/
if( auth_drive ) return auth_drive;
/**
* Otherwise, we now try to open the directory tree instead.
*/
return DVDOpenPath( path );
}
/* If it's none of the above, screw it. */
fprintf( stderr, "libdvdread: Could not open %s\n", path );
return 0;
}
void DVDClose( dvd_reader_t *dvd )
{
if( dvd ) {
if( dvd->dev ) DVDinput_close( dvd->dev );
if( dvd->path_root ) free( dvd->path_root );
free( dvd );
dvd = 0;
}
}
/**
* Open an unencrypted file on a DVD image file.
*/
static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
{
uint32_t start, len;
dvd_file_t *dvd_file;
start = UDFFindFile( dvd, filename, &len );
if( !start ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
return dvd_file;
}
/**
* Searches for <file> in directory <path>, ignoring case.
* Returns 0 and full filename in <filename>.
* or -1 on file not found.
* or -2 on path not found.
*/
static int findDirFile( const char *path, const char *file, char *filename )
{
DIR *dir;
struct dirent *ent;
dir = opendir( path );
if( !dir ) return -2;
while( ( ent = readdir( dir ) ) != NULL ) {
if( !strcasecmp( ent->d_name, file ) ) {
sprintf( filename, "%s%s%s", path,
( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
ent->d_name );
return 0;
}
}
return -1;
}
static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
{
char video_path[ PATH_MAX + 1 ];
const char *nodirfile;
int ret;
/* Strip off the directory for our search */
if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
nodirfile = &(file[ 10 ]);
} else {
nodirfile = file;
}
ret = findDirFile( dvd->path_root, nodirfile, filename );
if( ret < 0 ) {
/* Try also with adding the path, just in case. */
sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root );
ret = findDirFile( video_path, nodirfile, filename );
if( ret < 0 ) {
/* Try with the path, but in lower case. */
sprintf( video_path, "%s/video_ts/", dvd->path_root );
ret = findDirFile( video_path, nodirfile, filename );
if( ret < 0 ) {
return 0;
}
}
}
return 1;
}
/**
* Open an unencrypted file from a DVD directory tree.
*/
static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
{
char full_path[ PATH_MAX + 1 ];
dvd_file_t *dvd_file;
struct stat fileinfo;
dvd_input_t dev;
/* Get the full path of the file. */
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
dev = DVDinput_open( full_path );
if( !dev ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = 0;
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_devs[ 0 ] = dev;
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
return dvd_file;
}
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
uint32_t start, len;
dvd_file_t *dvd_file;
if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
}
start = UDFFindFile( dvd, filename, &len );
if( start == 0 ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
/*Hack*/ dvd_file->css_title = title << 1 | menu;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
/* Calculate the complete file size for every file in the VOBS */
if( !menu ) {
int cur;
for( cur = 2; cur < 10; cur++ ) {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
if( !UDFFindFile( dvd, filename, &len ) ) break;
dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
}
}
if( dvd->css_state == 1 /* Need key init */ ) {
initAllCSSKeys( dvd );
dvd->css_state = 2;
}
/*
if( DVDinput_seek( dvd_file->dvd->dev,
(int)start, DVDINPUT_SEEK_KEY ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
filename );
}
*/
return dvd_file;
}
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
char full_path[ PATH_MAX + 1 ];
struct stat fileinfo;
dvd_file_t *dvd_file;
int i;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
/*Hack*/ dvd_file->css_title = title << 1 | menu;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = 0;
if( menu ) {
dvd_input_t dev;
if( title == 0 ) {
sprintf( filename, "VIDEO_TS.VOB" );
} else {
sprintf( filename, "VTS_%02i_0.VOB", title );
}
if( !findDVDFile( dvd, filename, full_path ) ) {
free( dvd_file );
return 0;
}
dev = DVDinput_open( full_path );
if( dev == NULL ) {
free( dvd_file );
return 0;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_devs[ 0 ] = dev;
DVDinput_seek( dvd_file->title_devs[0], 0, DVDINPUT_SEEK_KEY );
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
} else {
for( i = 0; i < 9; ++i ) {
sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
if( !findDVDFile( dvd, filename, full_path ) ) {
break;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
break;
}
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_devs[ i ] = DVDinput_open( full_path );
dvd_file->filesize += dvd_file->title_sizes[ i ];
}
if( dvd_file->title_devs[ 0 ] ) {
DVDinput_seek( dvd_file->title_devs[ 0 ], 0, DVDINPUT_SEEK_KEY );
} else {
free( dvd_file );
return 0;
}
}
return dvd_file;
}
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
dvd_read_domain_t domain )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
switch( domain ) {
case DVD_READ_INFO_FILE:
if( titlenum == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
}
break;
case DVD_READ_INFO_BACKUP_FILE:
if( titlenum == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
}
break;
case DVD_READ_MENU_VOBS:
if( dvd->isImageFile ) {
return DVDOpenVOBUDF( dvd, titlenum, 1 );
} else {
return DVDOpenVOBPath( dvd, titlenum, 1 );
}
break;
case DVD_READ_TITLE_VOBS:
if( titlenum == 0 ) return 0;
if( dvd->isImageFile ) {
return DVDOpenVOBUDF( dvd, titlenum, 0 );
} else {
return DVDOpenVOBPath( dvd, titlenum, 0 );
}
break;
default:
fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
return 0;
}
if( dvd->isImageFile ) {
return DVDOpenFileUDF( dvd, filename );
} else {
return DVDOpenFilePath( dvd, filename );
}
}
void DVDCloseFile( dvd_file_t *dvd_file )
{
int i;
if( dvd_file ) {
if( dvd_file->dvd->isImageFile ) {
;
} else {
for( i = 0; i < 9; ++i ) {
if( dvd_file->title_devs[ i ] ) {
DVDinput_close( dvd_file->title_devs[i] );
}
}
}
free( dvd_file );
dvd_file = 0;
}
}
/* Internal, but used from dvd_udf.c */
int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted )
{
int ret;
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
ret = DVDinput_seek( device->dev, (int) lb_number, DVDINPUT_NOFLAGS );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number );
return 0;
}
return DVDinput_read( device->dev, (char *) data,
(int) block_count, encrypted );
}
/* This is using a single input and starting from 'dvd_file->lb_start' offset.
*
* Reads 'block_count' blocks from 'dvd_file' at block offset 'offset'
* into the buffer located at 'data' and if 'encrypted' is set
* descramble the data if it's encrypted. Returning either an
* negative error or the number of blocks read. */
static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, unsigned char *data,
int encrypted )
{
return DVDReadBlocksUDFRaw( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, data, encrypted );
}
/* This is using possibly several inputs and starting from an offset of '0'.
*
* Reads 'block_count' blocks from 'dvd_file' at block offset 'offset'
* into the buffer located at 'data' and if 'encrypted' is set
* descramble the data if it's encrypted. Returning either an
* negative error or the number of blocks read. */
static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
size_t block_count, unsigned char *data,
int encrypted )
{
int i;
int ret, ret2, off;
ret = 0;
ret2 = 0;
for( i = 0; i < 9; ++i ) {
if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */
if( offset < dvd_file->title_sizes[ i ] ) {
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
off = DVDinput_seek( dvd_file->title_devs[ i ],
(int)offset, DVDINPUT_NOFLAGS );
if( off < 0 || off != (int)offset ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return off < 0 ? off : 0;
}
ret = DVDinput_read( dvd_file->title_devs[ i ], data,
(int)block_count, encrypted );
break;
} else {
size_t part1_size = dvd_file->title_sizes[ i ] - offset;
/* FIXME: Really needs to be a while loop.
* (This is only true if you try and read >1GB at a time) */
/* Read part 1 */
off = DVDinput_seek( dvd_file->title_devs[ i ],
(int)offset, DVDINPUT_NOFLAGS );
if( off < 0 || off != (int)offset ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return off < 0 ? off : 0;
}
ret = DVDinput_read( dvd_file->title_devs[ i ], data,
(int)part1_size, encrypted );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
* also error from this read will not show in ret. */
/* Read part 2 */
off = DVDinput_seek( dvd_file->title_devs[ i + 1 ],
0, DVDINPUT_NOFLAGS );
if( off < 0 || off != 0 ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
0 );
return off < 0 ? off : 0;
}
ret2 = DVDinput_read( dvd_file->title_devs[ i + 1 ],
data + ( part1_size
* (int64_t)DVD_VIDEO_LB_LEN ),
(int)(block_count - part1_size),
encrypted );
if( ret2 < 0 ) return ret2;
break;
}
} else {
offset -= dvd_file->title_sizes[ i ];
}
}
return ret + ret2;
}
/* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. */
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, unsigned char *data )
{
int ret;
/* Hack, and it will still fail for multiple opens in a threaded app ! */
if( dvd_file->dvd->css_title != dvd_file->css_title ) {
dvd_file->dvd->css_title = dvd_file->css_title;
if( dvd_file->dvd->isImageFile ) {
DVDinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start );
} else {
DVDinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start );
}
}
if( dvd_file->dvd->isImageFile ) {
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
block_count, data, DVDINPUT_READ_DECRYPT );
} else {
ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset,
block_count, data, DVDINPUT_READ_DECRYPT );
}
return (ssize_t)ret;
}
int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
{
if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) {
return -1;
}
dvd_file->seek_pos = (uint32_t) offset;
return offset;
}
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
{
unsigned char *secbuf;
unsigned int numsec, seek_sector, seek_byte;
int ret;
seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1;
secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
if( !secbuf ) {
fprintf( stderr, "libdvdread: Can't allocate memory "
"for file read!\n" );
return 0;
}
if( dvd_file->dvd->isImageFile ) {
ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector,
(size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
} else {
ret = DVDReadBlocksPath( dvd_file, seek_sector,
(size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
}
if( ret != (int) numsec ) {
free( secbuf );
return ret < 0 ? ret : 0;
}
memcpy( data, &(secbuf[ seek_byte ]), byte_size );
free( secbuf );
dvd_file->seek_pos += byte_size;
return byte_size;
}
ssize_t DVDFileSize( dvd_file_t *dvd_file )
{
return dvd_file->filesize;
}
--- NEW FILE ---
#ifndef DVD_READER_H_INCLUDED
#define DVD_READER_H_INCLUDED
/*
* Copyright (C) 2001, 2002 Billy Biggs <vektor at dumbterm.net>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/types.h>
/**
* The length of one Logical Block of a DVD Video.
*/
#define DVD_VIDEO_LB_LEN 2048
/**
* Maximum length of filenames for UDF.
*/
#define MAX_UDF_FILE_NAME_LEN 2048
#ifdef __cplusplus
extern "C" {
#endif
typedef struct dvd_reader_s dvd_reader_t;
typedef struct dvd_file_s dvd_file_t;
/**
* dvd = DVDOpen(path);
*
* Opens a block device of a DVD-ROM file, or an image file, or a directory
* name for a mounted DVD or HD copy of a DVD. Returns 0 if we can't get any
* of those methods to work.
*
* If the given file is a block device, or is the mountpoint for a block
* device, then that device is used for CSS authentication using libdvdcss.
* If no device is available, then no CSS authentication is performed,
* and we hope that the image is decrypted.
*
* If the path given is a directory, then the files in that directory may be in
* any one of these formats:
*
* path/VIDEO_TS/VTS_01_1.VOB
* path/video_ts/vts_01_1.vob
* path/VTS_01_1.VOB
* path/vts_01_1.vob
*/
dvd_reader_t *DVDOpen( const char * );
/**
* DVDClose(dvd);
*
* Closes and cleans up the DVD reader object. You must close all open files
* before calling this function.
*/
void DVDClose( dvd_reader_t * );
/**
* INFO_FILE : VIDEO_TS.IFO (manager)
* VTS_XX_0.IFO (title)
*
* INFO_BACKUP_FILE: VIDEO_TS.BUP (manager)
* VTS_XX_0.BUP (title)
*
* MENU_VOBS : VIDEO_TS.VOB (manager)
* VTS_XX_0.VOB (title)
*
* TITLE_VOBS : VTS_XX_[1-9].VOB (title)
* All files in the title set are opened and
* read as a single file.
*/
typedef enum {
DVD_READ_INFO_FILE,
DVD_READ_INFO_BACKUP_FILE,
DVD_READ_MENU_VOBS,
DVD_READ_TITLE_VOBS
} dvd_read_domain_t;
/**
* dvd_file = DVDOpenFile(dvd, titlenum, domain);
*
* Opens a file on the DVD given the title number and domain. If the title
* number is 0, the video manager information is opened
* (VIDEO_TS.[IFO,BUP,VOB]). Returns a file structure which may be used for
* reads, or 0 if the file was not found.
*/
dvd_file_t *DVDOpenFile( dvd_reader_t *, int,
dvd_read_domain_t );
/**
* DVDCloseFile(dvd_file);
*
* Closes a file and frees the associated structure.
*/
void DVDCloseFile( dvd_file_t * );
/**
* blocks_read = DVDReadBlocks(dvd_file, offset, block_count, data);
*
* Reads block_count number of blocks from the file at the given block offset.
* Returns number of blocks read on success, -1 on error. This call is only
* for reading VOB data, and should not be used when reading the IFO files.
* When reading from an encrypted drive, blocks are decrypted using libdvdcss
* where required.
*/
ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * );
/**
* offset_set = DVDFileSeek(dvd_file, seek_offset);
*
* Seek to the given position in the file. Returns the resulting position in
* bytes from the beginning of the file. The seek position is only used for
* byte reads from the file, the block read call always reads from the given
* offset.
*/
int DVDFileSeek( dvd_file_t *, int );
/**
* bytes_read = DVDReadBytes(dvd_file, data, bytes);
*
* Reads the given number of bytes from the file. This call can only be used
* on the information files, and may not be used for reading from a VOB. This
* reads from and increments the currrent seek position for the file.
*/
ssize_t DVDReadBytes( dvd_file_t *, void *, size_t );
/**
* blocks = DVDFileSize(dvd_file);
*
* Returns the file size in blocks.
*/
ssize_t DVDFileSize( dvd_file_t * );
#ifdef __cplusplus
};
#endif
#endif /* DVD_READER_H_INCLUDED */
--- NEW FILE ---
/*
* This code is based on dvdudf by:
* Christian Wolff <scarabaeus at convergence.de>.
*
* Modifications by:
* Billy Biggs <vektor at dumbterm.net>.
*
* dvdudf: parse and read the UDF volume information of a DVD Video
* Copyright (C) 1999 Christian Wolff for convergence integrated media
* GmbH The author can be reached at scarabaeus at convergence.de, the
* project's page is at http://linuxtv.org/dvd/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. Or, point your browser to
* http://www.gnu.org/copyleft/gpl.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <inttypes.h>
#include "dvd_reader.h"
#include "dvd_udf.h"
/* Private but located in/shared with dvd_reader.c */
extern int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted );
/* It's required to either fail or deliver all the blocks asked for. */
static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted )
{
int ret;
size_t count = block_count;
while(count > 0) {
ret = DVDReadBlocksUDFRaw(device, lb_number, count, data, encrypted);
if(ret <= 0) {
/* One of the reads failed or nothing more to read, too bad.
* We won't even bother returning the reads that went ok. */
return ret;
}
count -= (size_t)ret;
lb_number += (uint32_t)ret;
}
return block_count;
}
#ifndef NULL
#define NULL ((void *)0)
#endif
struct Partition {
int valid;
char VolumeDesc[128];
uint16_t Flags;
uint16_t Number;
char Contents[32];
uint32_t AccessType;
uint32_t Start;
uint32_t Length;
};
struct AD {
uint32_t Location;
uint32_t Length;
uint8_t Flags;
uint16_t Partition;
};
/* For direct data access, LSB first */
#define GETN1(p) ((uint8_t)data[p])
#define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8))
#define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \
| ((uint32_t)data[(p) + 2] << 16))
#define GETN4(p) ((uint32_t)data[p] \
| ((uint32_t)data[(p) + 1] << 8) \
| ((uint32_t)data[(p) + 2] << 16) \
| ((uint32_t)data[(p) + 3] << 24))
/* This is wrong with regard to endianess */
#define GETN(p, n, target) memcpy(target, &data[p], n)
static int Unicodedecode( uint8_t *data, int len, char *target )
{
int p = 1, i = 0;
if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do {
if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */
if( p < len ) {
target[ i++ ] = data[ p++ ];
}
} while( p < len );
target[ i ] = '\0';
return 0;
}
static int UDFDescriptor( uint8_t *data, uint16_t *TagID )
{
*TagID = GETN2(0);
// TODO: check CRC 'n stuff
return 0;
}
static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location )
{
*Length = GETN4(0);
*Location = GETN4(4);
return 0;
}
static int UDFShortAD( uint8_t *data, struct AD *ad,
struct Partition *partition )
{
ad->Length = GETN4(0);
ad->Flags = ad->Length >> 30;
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(4);
ad->Partition = partition->Number; // use number of current partition
return 0;
}
static int UDFLongAD( uint8_t *data, struct AD *ad )
{
ad->Length = GETN4(0);
ad->Flags = ad->Length >> 30;
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(4);
ad->Partition = GETN2(8);
//GETN(10, 6, Use);
return 0;
}
static int UDFExtAD( uint8_t *data, struct AD *ad )
{
ad->Length = GETN4(0);
ad->Flags = ad->Length >> 30;
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(12);
ad->Partition = GETN2(16);
//GETN(10, 6, Use);
return 0;
}
static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags )
{
*FileType = GETN1(11);
*Flags = GETN2(18);
return 0;
}
static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number,
char *Contents, uint32_t *Start, uint32_t *Length )
{
*Flags = GETN2(20);
*Number = GETN2(22);
GETN(24, 32, Contents);
*Start = GETN4(188);
*Length = GETN4(192);
return 0;
}
/**
* Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1
* on error.
*/
static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor )
{
uint32_t lbsize, MT_L, N_PM;
Unicodedecode(&data[84], 128, VolumeDescriptor);
lbsize = GETN4(212); // should be 2048
MT_L = GETN4(264); // should be 6
N_PM = GETN4(268); // should be 1
if (lbsize != DVD_VIDEO_LB_LEN) return 1;
return 0;
}
static int UDFFileEntry( uint8_t *data, uint8_t *FileType,
struct Partition *partition, struct AD *ad )
{
uint16_t flags;
uint32_t L_EA, L_AD;
unsigned int p;
UDFICB( &data[ 16 ], FileType, &flags );
/* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */
ad->Length = GETN4( 60 ); // Really 8 bytes a 56
ad->Flags = 0;
ad->Location = 0; // what should we put here?
ad->Partition = partition->Number; // use number of current partition
L_EA = GETN4( 168 );
L_AD = GETN4( 172 );
p = 176 + L_EA;
while( p < 176 + L_EA + L_AD ) {
switch( flags & 0x0007 ) {
case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break;
case 1: UDFLongAD( &data[ p ], ad ); p += 16; break;
case 2: UDFExtAD( &data[ p ], ad ); p += 20; break;
case 3:
switch( L_AD ) {
case 8: UDFShortAD( &data[ p ], ad, partition ); break;
case 16: UDFLongAD( &data[ p ], ad ); break;
case 20: UDFExtAD( &data[ p ], ad ); break;
}
p += L_AD;
break;
default:
p += L_AD; break;
}
}
return 0;
}
static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics,
char *FileName, struct AD *FileICB )
{
uint8_t L_FI;
uint16_t L_IU;
*FileCharacteristics = GETN1(18);
L_FI = GETN1(19);
UDFLongAD(&data[20], FileICB);
L_IU = GETN2(36);
if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName);
else FileName[0] = '\0';
return 4 * ((38 + L_FI + L_IU + 3) / 4);
}
/**
* Maps ICB to FileAD
* ICB: Location of ICB of directory to scan
* FileType: Type of the file
* File: Location of file the ICB is pointing to
* return 1 on success, 0 on error;
*/
static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
struct Partition *partition, struct AD *File )
{
uint8_t LogBlock[DVD_VIDEO_LB_LEN];
uint32_t lbnum;
uint16_t TagID;
lbnum = partition->Start + ICB.Location;
do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
} else {
UDFDescriptor( LogBlock, &TagID );
}
if( TagID == 261 ) {
UDFFileEntry( LogBlock, FileType, partition, File );
return 1;
};
} while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 )
/ DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) );
return 0;
}
/**
* Dir: Location of directory to scan
* FileName: Name of file to look for
* FileICB: Location of ICB of the found file
* return 1 on success, 0 on error;
*/
static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
struct Partition *partition, struct AD *FileICB )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
uint8_t directory[ 2 * DVD_VIDEO_LB_LEN ];
uint32_t lbnum;
uint16_t TagID;
uint8_t filechar;
unsigned int p;
/* Scan dir for ICB of file */
lbnum = partition->Start + Dir.Location;
if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
return 0;
}
p = 0;
while( p < Dir.Length ) {
if( p > DVD_VIDEO_LB_LEN ) {
++lbnum;
p -= DVD_VIDEO_LB_LEN;
Dir.Length -= DVD_VIDEO_LB_LEN;
if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
return 0;
}
}
UDFDescriptor( &directory[ p ], &TagID );
if( TagID == 257 ) {
p += UDFFileIdentifier( &directory[ p ], &filechar,
filename, FileICB );
if( !strcasecmp( FileName, filename ) ) {
return 1;
}
} else {
return 0;
}
}
return 0;
}
/**
* Looks for partition on the disc. Returns 1 if partition found, 0 on error.
* partnum: Number of the partition, starting at 0.
* part: structure to fill with the partition information
*/
static int UDFFindPartition( dvd_reader_t *device, int partnum,
struct Partition *part )
{
uint8_t LogBlock[ DVD_VIDEO_LB_LEN ], Anchor[ DVD_VIDEO_LB_LEN ];
uint32_t lbnum, MVDS_location, MVDS_length;
uint16_t TagID;
uint32_t lastsector;
int i, terminate, volvalid;
/* Find Anchor */
lastsector = 0;
lbnum = 256; /* Try #1, prime anchor */
terminate = 0;
for(;;) {
if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
UDFDescriptor( Anchor, &TagID );
} else {
TagID = 0;
}
if (TagID != 2) {
/* Not an anchor */
if( terminate ) return 0; /* Final try failed */
if( lastsector ) {
/* We already found the last sector. Try #3, alternative
* backup anchor. If that fails, don't try again.
*/
lbnum = lastsector;
terminate = 1;
} else {
/* TODO: Find last sector of the disc (this is optional). */
if( lastsector ) {
/* Try #2, backup anchor */
lbnum = lastsector - 256;
} else {
/* Unable to find last sector */
return 0;
}
}
} else {
/* It's an anchor! We can leave */
break;
}
}
/* Main volume descriptor */
UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location );
part->valid = 0;
volvalid = 0;
part->VolumeDesc[ 0 ] = '\0';
i = 1;
do {
/* Find Volume Descriptor */
lbnum = MVDS_location;
do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
} else {
UDFDescriptor( LogBlock, &TagID );
}
if( ( TagID == 5 ) && ( !part->valid ) ) {
/* Partition Descriptor */
UDFPartition( LogBlock, &part->Flags, &part->Number,
part->Contents, &part->Start, &part->Length );
part->valid = ( partnum == part->Number );
} else if( ( TagID == 6 ) && ( !volvalid ) ) {
/* Logical Volume Descriptor */
if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) {
/* TODO: sector size wrong! */
} else {
volvalid = 1;
}
}
} while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
/ DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
&& ( ( !part->valid ) || ( !volvalid ) ) );
if( ( !part->valid) || ( !volvalid ) ) {
/* Backup volume descriptor */
UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location );
}
} while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );
/* We only care for the partition, not the volume */
return part->valid;
}
uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
uint32_t *filesize )
{
uint8_t LogBlock[ DVD_VIDEO_LB_LEN ];
uint32_t lbnum;
uint16_t TagID;
struct Partition partition;
struct AD RootICB, File, ICB;
char tokenline[ MAX_UDF_FILE_NAME_LEN ];
char *token;
uint8_t filetype;
*filesize = 0;
tokenline[0] = '\0';
strcat( tokenline, filename );
/* Find partition, 0 is the standard location for DVD Video.*/
if( !UDFFindPartition( device, 0, &partition ) ) return 0;
/* Find root dir ICB */
lbnum = partition.Start;
do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
} else {
UDFDescriptor( LogBlock, &TagID );
}
/* File Set Descriptor */
if( TagID == 256 ) { // File Set Descriptor
UDFLongAD( &LogBlock[ 400 ], &RootICB );
}
} while( ( lbnum < partition.Start + partition.Length )
&& ( TagID != 8 ) && ( TagID != 256 ) );
/* Sanity checks. */
if( TagID != 256 ) return 0;
if( RootICB.Partition != 0 ) return 0;
/* Find root dir */
if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0;
if( filetype != 4 ) return 0; /* Root dir should be dir */
/* Tokenize filepath */
token = strtok(tokenline, "/");
while( token != NULL ) {
if( !UDFScanDir( device, File, token, &partition, &ICB ) ) return 0;
if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) return 0;
token = strtok( NULL, "/" );
}
/* Sanity check. */
if( File.Partition != 0 ) return 0;
*filesize = File.Length;
/* Hack to not return partition.Start for empty files. */
if( !File.Location )
return 0;
else
return partition.Start + File.Location;
}
--- NEW FILE ---
#ifndef DVD_UDF_H_INCLUDED
#define DVD_UDF_H_INCLUDED
/*
* This code is based on dvdudf by:
* Christian Wolff <scarabaeus at convergence.de>.
*
* Modifications by:
* Billy Biggs <vektor at dumbterm.net>.
*
* dvdudf: parse and read the UDF volume information of a DVD Video
* Copyright (C) 1999 Christian Wolff for convergence integrated media
* GmbH The author can be reached at scarabaeus at convergence.de, the
* project's page is at http://linuxtv.org/dvd/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. Or, point your browser to
* http://www.gnu.org/copyleft/gpl.html
*/
#include <inttypes.h>
#include "dvd_reader.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Looks for a file on the UDF disc/imagefile and returns the block number
* where it begins, or 0 if it is not found. The filename should be an
* absolute pathname on the UDF filesystem, starting with '/'. For example,
* '/VIDEO_TS/VTS_01_1.IFO'. On success, filesize will be set to the size of
* the file in bytes.
*/
uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size );
#ifdef __cplusplus
};
#endif
#endif /* DVD_UDF_H_INCLUDED */
--- NEW FILE ---
/*
* Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
[...1010 lines suppressed...]
printf("\nVideo Title Set Menu VOBU address map\n");
printf( "-----------------\n");
if(ifohandle->menu_vobu_admap) {
ifoPrint_VOBU_ADMAP(ifohandle->menu_vobu_admap);
} else {
printf("No Menu VOBU address map present\n");
}
printf("\nCell Adress table\n");
printf( "-----------------\n");
ifoPrint_C_ADT(ifohandle->vts_c_adt);
printf("\nVideo Title Set VOBU address map\n");
printf( "-----------------\n");
ifoPrint_VOBU_ADMAP(ifohandle->vts_vobu_admap);
}
ifoClose(ifohandle);
}
--- NEW FILE ---
#ifndef IFO_PRINT_H_INCLUDED
#define IFO_PRINT_H_INCLUDED
/*
* Copyright (C) 2000, 2001 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <dvdread/ifo_types.h>
#include <dvdread/dvd_reader.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* This file provides example functions for printing information about the IFO
* file to stdout.
*/
/**
* Print the complete parsing information for the given file.
*/
/* ifoPrint(dvd, title); */
void ifoPrint(dvd_reader_t *, int);
void ifoPrint_VMGI_MAT(vmgi_mat_t *);
void ifoPrint_VTSI_MAT(vtsi_mat_t *);
void ifoPrint_PTL_MAIT(ptl_mait_t *);
void ifoPrint_VTS_ATRT(vts_atrt_t *);
void ifoPrint_TT_SRPT(tt_srpt_t *);
void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *);
void ifoPrint_PGC(pgc_t *);
void ifoPrint_PGCIT(pgcit_t *);
void ifoPrint_PGCI_UT(pgci_ut_t *);
void ifoPrint_C_ADT(c_adt_t *);
void ifoPrint_VOBU_ADMAP(vobu_admap_t *);
#ifdef __cplusplus
};
#endif
#endif /* IFO_PRINT_H_INCLUDED */
--- NEW FILE ---
/*
* Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
[...1759 lines suppressed...]
fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
free(txtdt_mgi);
ifofile->txtdt_mgi = 0;
return 0;
}
// fprintf(stderr, "-- Not done yet --\n");
return 1;
}
void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) {
if(!ifofile)
return;
if(ifofile->txtdt_mgi) {
free(ifofile->txtdt_mgi);
ifofile->txtdt_mgi = 0;
}
}
--- NEW FILE ---
#ifndef IFO_READ_H_INCLUDED
#define IFO_READ_H_INCLUDED
/*
* Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <dvdread/ifo_types.h>
#include <dvdread/dvd_reader.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* handle = ifoOpen(dvd, title);
*
* Opens an IFO and reads in all the data for the IFO file corresponding to the
* given title. If title 0 is given, the video manager IFO file is read.
* Returns a handle to a completely parsed structure.
*/
ifo_handle_t *ifoOpen(dvd_reader_t *, int );
/**
* handle = ifoOpenVMGI(dvd);
*
* Opens an IFO and reads in _only_ the vmgi_mat data. This call can be used
* together with the calls below to read in each segment of the IFO file on
* demand.
*/
ifo_handle_t *ifoOpenVMGI(dvd_reader_t *);
/**
* handle = ifoOpenVTSI(dvd, title);
*
* Opens an IFO and reads in _only_ the vtsi_mat data. This call can be used
* together with the calls below to read in each segment of the IFO file on
* demand.
*/
ifo_handle_t *ifoOpenVTSI(dvd_reader_t *, int);
/**
* ifoClose(ifofile);
* Cleans up the IFO information. This will free all data allocated for the
* substructures.
*/
void ifoClose(ifo_handle_t *);
/**
* The following functions are for reading only part of the VMGI/VTSI files.
* Returns 1 if the data was successfully read and 0 on error.
*/
/**
* okay = ifoRead_PLT_MAIT(ifofile);
*
* Read in the Parental Management Information table, filling the
* ifofile->ptl_mait structure and its substructures. This data is only
* located in the video manager information file. This fills the
* ifofile->ptl_mait structure and all its substructures.
*/
int ifoRead_PTL_MAIT(ifo_handle_t *);
/**
* okay = ifoRead_VTS_ATRT(ifofile);
*
* Read in the attribute table for the main menu vob, filling the
* ifofile->vts_atrt structure and its substructures. Only located in the
* video manager information file. This fills in the ifofile->vts_atrt
* structure and all its substructures.
*/
int ifoRead_VTS_ATRT(ifo_handle_t *);
/**
* okay = ifoRead_TT_SRPT(ifofile);
*
* Reads the title info for the main menu, filling the ifofile->tt_srpt
* structure and its substructures. This data is only located in the video
* manager information file. This structure is mandatory in the IFO file.
*/
int ifoRead_TT_SRPT(ifo_handle_t *);
/**
* okay = ifoRead_VTS_PTT_SRPT(ifofile);
*
* Reads in the part of title search pointer table, filling the
* ifofile->vts_ptt_srpt structure and its substructures. This data is only
* located in the video title set information file. This structure is
* mandatory, and must be included in the VTSI file.
*/
int ifoRead_VTS_PTT_SRPT(ifo_handle_t *);
/**
* okay = ifoRead_FP_PGC(ifofile);
*
* Reads in the first play program chain data, filling the
* ifofile->first_play_pgc structure. This data is only located in the video
* manager information file. This structure is mandatory, and must be included
* in the VMGI file. **Possibly this is only optional.**
*/
int ifoRead_FP_PGC(ifo_handle_t *);
/**
* okay = ifoRead_PGCIT(ifofile);
*
* Reads in the program chain information table for the video title set. Fills
* in the ifofile->vts_pgcit structure and its substructures, which includes
* the data for each program chain in the set. This data is only located in
* the video title set information file. This structure is mandatory, and must
* be included in the VTSI file.
*/
int ifoRead_PGCIT(ifo_handle_t *);
/**
* okay = ifoRead_PGCI_UT(ifofile);
*
* Reads in the menu PGCI unit table for the menu VOB. For the video manager,
* this corresponds to the VIDEO_TS.VOB file, and for each title set, this
* corresponds to the VTS_XX_0.VOB file. This data is located in both the
* video manager and video title set information files. For VMGI files, this
* fills the ifofile->vmgi_pgci_ut structure and all its substructures. For
* VTSI files, this fills the ifofile->vtsm_pgci_ut structure.
*/
int ifoRead_PGCI_UT(ifo_handle_t *);
/**
* okay = ifoRead_C_ADT(ifofile);
*
* Reads in the cell address table for the menu VOB. For the video manager,
* this corresponds to the VIDEO_TS.VOB file, and for each title set, this
* corresponds to the VTS_XX_0.VOB file. This data is located in both the
* video manager and video title set information files. For VMGI files, this
* fills the ifofile->vmgm_c_adt structure and all its substructures. For VTSI
* files, this fills the ifofile->vtsm_c_adt structure.
*/
int ifoRead_C_ADT(ifo_handle_t *);
/**
* okay = ifoRead_TITLE_C_ADT(ifofile);
*
* Reads in the cell address table for the video title set corresponding to
* this IFO file. This data is only located in the video title set information
* file. This structure is mandatory, and must be included in the VTSI file.
* This call fills the ifofile->vts_c_adt structure and its substructures.
*/
int ifoRead_TITLE_C_ADT(ifo_handle_t *);
/**
* okay = ifoRead_VOBU_ADMAP(ifofile);
*
* Reads in the VOBU address map for the menu VOB. For the video manager, this
* corresponds to the VIDEO_TS.VOB file, and for each title set, this
* corresponds to the VTS_XX_0.VOB file. This data is located in both the
* video manager and video title set information files. For VMGI files, this
* fills the ifofile->vmgm_vobu_admap structure and all its substructures. For
* VTSI files, this fills the ifofile->vtsm_vobu_admap structure.
*/
int ifoRead_VOBU_ADMAP(ifo_handle_t *);
/**
* okay = ifoRead_TITLE_VOBU_ADMAP(ifofile);
*
* Reads in the VOBU address map for the associated video title set. This data
* is only located in the video title set information file. This structure is
* mandatory, and must be included in the VTSI file. Fills the
* ifofile->vts_vobu_admap structure and its substructures.
*/
int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *);
/**
* okay = ifoRead_TXTDT_MGI(ifofile);
*
* Reads in the text data strings for the DVD. Fills the ifofile->txtdt_mgi
* structure and all its substructures. This data is only located in the video
* manager information file. This structure is mandatory, and must be included
* in the VMGI file.
*/
int ifoRead_TXTDT_MGI(ifo_handle_t *);
/**
* The following functions are used for freeing parsed sections of the
* ifo_handle_t structure and the allocated substructures. The free calls
* below are safe: they will not mind if you attempt to free part of an IFO
* file which was not read in or which does not exist.
*/
void ifoFree_PTL_MAIT(ifo_handle_t *);
void ifoFree_VTS_ATRT(ifo_handle_t *);
void ifoFree_TT_SRPT(ifo_handle_t *);
void ifoFree_VTS_PTT_SRPT(ifo_handle_t *);
void ifoFree_FP_PGC(ifo_handle_t *);
void ifoFree_PGCIT(ifo_handle_t *);
void ifoFree_PGCI_UT(ifo_handle_t *);
void ifoFree_C_ADT(ifo_handle_t *);
void ifoFree_TITLE_C_ADT(ifo_handle_t *);
void ifoFree_VOBU_ADMAP(ifo_handle_t *);
void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *);
void ifoFree_TXTDT_MGI(ifo_handle_t *);
#ifdef __cplusplus
};
#endif
#endif /* IFO_READ_H_INCLUDED */
--- NEW FILE ---
#ifndef IFO_TYPES_H_INCLUDED
#define IFO_TYPES_H_INCLUDED
/*
* Copyright (C) 2000, 2001 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <inttypes.h>
#include <dvdread/dvd_reader.h>
#undef ATTRIBUTE_PACKED
#undef PRAGMA_PACK_BEGIN
#undef PRAGMA_PACK_END
#if defined(__GNUC__)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
#define ATTRIBUTE_PACKED __attribute__ ((packed))
#define PRAGMA_PACK 0
#endif
#endif
#if !defined(ATTRIBUTE_PACKED)
#define ATTRIBUTE_PACKED
#define PRAGMA_PACK 1
#endif
#if PRAGMA_PACK
#pragma pack(1)
#endif
/**
* Common
*
* The following structures are used in both the VMGI and VTSI.
*/
/**
* DVD Time Information.
*/
typedef struct {
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t frame_u; // The two high bits are the frame rate.
} ATTRIBUTE_PACKED dvd_time_t;
/**
* Type to store per-command data.
*/
typedef struct {
uint8_t bytes[8];
} ATTRIBUTE_PACKED vm_cmd_t;
#define COMMAND_DATA_SIZE 8
/**
* Video Attributes.
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int mpeg_version : 2;
unsigned int video_format : 2;
unsigned int display_aspect_ratio : 2;
unsigned int permitted_df : 2;
unsigned int line21_cc_1 : 1;
unsigned int line21_cc_2 : 1;
unsigned int unknown1 : 2;
unsigned int picture_size : 2;
unsigned int letterboxed : 1;
unsigned int film_mode : 1;
#else
unsigned int permitted_df : 2;
unsigned int display_aspect_ratio : 2;
unsigned int video_format : 2;
unsigned int mpeg_version : 2;
unsigned int film_mode : 1;
unsigned int letterboxed : 1;
unsigned int picture_size : 2;
unsigned int unknown1 : 2;
unsigned int line21_cc_2 : 1;
unsigned int line21_cc_1 : 1;
#endif
} ATTRIBUTE_PACKED video_attr_t;
/**
* Audio Attributes. (Incomplete/Wrong?)
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int audio_format : 3;
unsigned int multichannel_extension : 1;
unsigned int lang_type : 2;
unsigned int application_mode : 2;
unsigned int quantization : 2;
unsigned int sample_frequency : 2;
unsigned int unknown1 : 1;
unsigned int channels : 3;
#else
unsigned int application_mode : 2;
unsigned int lang_type : 2;
unsigned int multichannel_extension : 1;
unsigned int audio_format : 3;
unsigned int channels : 3;
unsigned int unknown1 : 1;
unsigned int sample_frequency : 2;
unsigned int quantization : 2;
#endif
uint16_t lang_code;
uint8_t lang_code2; // ??
uint8_t lang_extension;
uint16_t unknown2;
} ATTRIBUTE_PACKED audio_attr_t;
/**
* Subpicture Attributes.(Incomplete/Wrong)
*/
typedef struct {
/*
* type: 0 not specified
* 1 language
* 2 other
* coding mode: 0 run length
* 1 extended
* 2 other
* language: indicates language if type == 1
* lang extension: if type == 1 contains the lang extension
*/
uint8_t type;
uint8_t zero1;
uint16_t lang_code;
uint8_t lang_extension;
uint8_t zero2;
} ATTRIBUTE_PACKED subp_attr_t;
/**
* PGC Command Table.
*/
typedef struct {
uint16_t nr_of_pre;
uint16_t nr_of_post;
uint16_t nr_of_cell;
uint16_t zero_1;
vm_cmd_t *pre_cmds;
vm_cmd_t *post_cmds;
vm_cmd_t *cell_cmds;
} ATTRIBUTE_PACKED pgc_command_tbl_t;
#define PGC_COMMAND_TBL_SIZE 8
/**
* PGC Program Map
*/
typedef uint8_t pgc_program_map_t;
/**
* Cell Playback Information.
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int block_mode : 2;
unsigned int block_type : 2;
unsigned int seamless_play : 1;
unsigned int interleaved : 1;
unsigned int stc_discontinuity: 1;
unsigned int seamless_angle : 1;
unsigned int unknown1 : 1;
unsigned int restricted : 1;
unsigned int unknown2 : 6;
#else
unsigned int seamless_angle : 1;
unsigned int stc_discontinuity: 1;
unsigned int interleaved : 1;
unsigned int seamless_play : 1;
unsigned int block_type : 2;
unsigned int block_mode : 2;
unsigned int unknown2 : 6;
unsigned int restricted : 1;
unsigned int unknown1 : 1;
#endif
uint8_t still_time;
uint8_t cell_cmd_nr;
dvd_time_t playback_time;
uint32_t first_sector;
uint32_t first_ilvu_end_sector;
uint32_t last_vobu_start_sector;
uint32_t last_sector;
} ATTRIBUTE_PACKED cell_playback_t;
#define BLOCK_TYPE_NONE 0x0
#define BLOCK_TYPE_ANGLE_BLOCK 0x1
#define BLOCK_MODE_NOT_IN_BLOCK 0x0
#define BLOCK_MODE_FIRST_CELL 0x1
#define BLOCK_MODE_IN_BLOCK 0x2
#define BLOCK_MODE_LAST_CELL 0x3
/**
* Cell Position Information.
*/
typedef struct {
uint16_t vob_id_nr;
uint8_t zero_1;
uint8_t cell_nr;
} ATTRIBUTE_PACKED cell_position_t;
/**
* User Operations.
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int zero : 7; // 25-31
unsigned int video_pres_mode_change : 1; // 24
unsigned int karaoke_audio_pres_mode_change : 1; // 23
unsigned int angle_change : 1; // 22
unsigned int subpic_stream_change : 1; // 21
unsigned int audio_stream_change : 1; // 20
unsigned int pause_on : 1; // 19
unsigned int still_off : 1; // 18
unsigned int button_select_or_activate : 1; // 17
unsigned int resume : 1; // 16
unsigned int chapter_menu_call : 1; // 15
unsigned int angle_menu_call : 1; // 14
unsigned int audio_menu_call : 1; // 13
unsigned int subpic_menu_call : 1; // 12
unsigned int root_menu_call : 1; // 11
unsigned int title_menu_call : 1; // 10
unsigned int backward_scan : 1; // 9
unsigned int forward_scan : 1; // 8
unsigned int next_pg_search : 1; // 7
unsigned int prev_or_top_pg_search : 1; // 6
unsigned int time_or_chapter_search : 1; // 5
unsigned int go_up : 1; // 4
unsigned int stop : 1; // 3
unsigned int title_play : 1; // 2
unsigned int chapter_search_or_play : 1; // 1
unsigned int title_or_time_play : 1; // 0
#else
unsigned int video_pres_mode_change : 1; // 24
unsigned int zero : 7; // 25-31
unsigned int resume : 1; // 16
unsigned int button_select_or_activate : 1; // 17
unsigned int still_off : 1; // 18
unsigned int pause_on : 1; // 19
unsigned int audio_stream_change : 1; // 20
unsigned int subpic_stream_change : 1; // 21
unsigned int angle_change : 1; // 22
unsigned int karaoke_audio_pres_mode_change : 1; // 23
unsigned int forward_scan : 1; // 8
unsigned int backward_scan : 1; // 9
unsigned int title_menu_call : 1; // 10
unsigned int root_menu_call : 1; // 11
unsigned int subpic_menu_call : 1; // 12
unsigned int audio_menu_call : 1; // 13
unsigned int angle_menu_call : 1; // 14
unsigned int chapter_menu_call : 1; // 15
unsigned int title_or_time_play : 1; // 0
unsigned int chapter_search_or_play : 1; // 1
unsigned int title_play : 1; // 2
unsigned int stop : 1; // 3
unsigned int go_up : 1; // 4
unsigned int time_or_chapter_search : 1; // 5
unsigned int prev_or_top_pg_search : 1; // 6
unsigned int next_pg_search : 1; // 7
#endif
} ATTRIBUTE_PACKED user_ops_t;
/**
* Program Chain Information.
*/
typedef struct {
uint16_t zero_1;
uint8_t nr_of_programs;
uint8_t nr_of_cells;
dvd_time_t playback_time;
user_ops_t prohibited_ops;
uint16_t audio_control[8]; /* New type? */
uint32_t subp_control[32]; /* New type? */
uint16_t next_pgc_nr;
uint16_t prev_pgc_nr;
uint16_t goup_pgc_nr;
uint8_t still_time;
uint8_t pg_playback_mode;
uint32_t palette[16]; /* New type struct {zero_1, Y, Cr, Cb} ? */
uint16_t command_tbl_offset;
uint16_t program_map_offset;
uint16_t cell_playback_offset;
uint16_t cell_position_offset;
pgc_command_tbl_t *command_tbl;
pgc_program_map_t *program_map;
cell_playback_t *cell_playback;
cell_position_t *cell_position;
} ATTRIBUTE_PACKED pgc_t;
#define PGC_SIZE 236
/**
* Program Chain Information Search Pointer.
*/
typedef struct {
uint8_t entry_id;
#ifdef WORDS_BIGENDIAN
unsigned int block_mode : 2;
unsigned int block_type : 2;
unsigned int unknown1 : 4;
#else
unsigned int unknown1 : 4;
unsigned int block_type : 2;
unsigned int block_mode : 2;
#endif
uint16_t ptl_id_mask;
uint32_t pgc_start_byte;
pgc_t *pgc;
} ATTRIBUTE_PACKED pgci_srp_t;
#define PGCI_SRP_SIZE 8
/**
* Program Chain Information Table.
*/
typedef struct {
uint16_t nr_of_pgci_srp;
uint16_t zero_1;
uint32_t last_byte;
pgci_srp_t *pgci_srp;
} ATTRIBUTE_PACKED pgcit_t;
#define PGCIT_SIZE 8
/**
* Menu PGCI Language Unit.
*/
typedef struct {
uint16_t lang_code;
uint8_t zero_1;
uint8_t exists;
uint32_t lang_start_byte;
pgcit_t *pgcit;
} ATTRIBUTE_PACKED pgci_lu_t;
#define PGCI_LU_SIZE 8
/**
* Menu PGCI Unit Table.
*/
typedef struct {
uint16_t nr_of_lus;
uint16_t zero_1;
uint32_t last_byte;
pgci_lu_t *lu;
} ATTRIBUTE_PACKED pgci_ut_t;
#define PGCI_UT_SIZE 8
/**
* Cell Address Information.
*/
typedef struct {
uint16_t vob_id;
uint8_t cell_id;
uint8_t zero_1;
uint32_t start_sector;
uint32_t last_sector;
} ATTRIBUTE_PACKED cell_adr_t;
/**
* Cell Address Table.
*/
typedef struct {
uint16_t nr_of_vobs; /* VOBs */
uint16_t zero_1;
uint32_t last_byte;
cell_adr_t *cell_adr_table;
} ATTRIBUTE_PACKED c_adt_t;
#define C_ADT_SIZE 8
/**
* VOBU Address Map.
*/
typedef struct {
uint32_t last_byte;
uint32_t *vobu_start_sectors;
} ATTRIBUTE_PACKED vobu_admap_t;
#define VOBU_ADMAP_SIZE 4
/**
* VMGI
*
* The following structures relate to the Video Manager.
*/
/**
* Video Manager Information Management Table.
*/
typedef struct {
char vmg_identifier[12];
uint32_t vmg_last_sector;
uint8_t zero_1[12];
uint32_t vmgi_last_sector;
uint8_t zero_2;
uint8_t specification_version;
uint32_t vmg_category;
uint16_t vmg_nr_of_volumes;
uint16_t vmg_this_volume_nr;
uint8_t disc_side;
uint8_t zero_3[19];
uint16_t vmg_nr_of_title_sets; /* Number of VTSs. */
char provider_identifier[32];
uint64_t vmg_pos_code;
uint8_t zero_4[24];
uint32_t vmgi_last_byte;
uint32_t first_play_pgc;
uint8_t zero_5[56];
uint32_t vmgm_vobs; /* sector */
uint32_t tt_srpt; /* sector */
uint32_t vmgm_pgci_ut; /* sector */
uint32_t ptl_mait; /* sector */
uint32_t vts_atrt; /* sector */
uint32_t txtdt_mgi; /* sector */
uint32_t vmgm_c_adt; /* sector */
uint32_t vmgm_vobu_admap; /* sector */
uint8_t zero_6[32];
video_attr_t vmgm_video_attr;
uint8_t zero_7;
uint8_t nr_of_vmgm_audio_streams; // should be 0 or 1
audio_attr_t vmgm_audio_attr;
audio_attr_t zero_8[7];
uint8_t zero_9[17];
uint8_t nr_of_vmgm_subp_streams; // should be 0 or 1
subp_attr_t vmgm_subp_attr;
subp_attr_t zero_10[27]; /* XXX: how much 'padding' here? */
} ATTRIBUTE_PACKED vmgi_mat_t;
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int zero_1 : 1;
unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title
unsigned int jlc_exists_in_cell_cmd : 1;
unsigned int jlc_exists_in_prepost_cmd : 1;
unsigned int jlc_exists_in_button_cmd : 1;
unsigned int jlc_exists_in_tt_dom : 1;
unsigned int chapter_search_or_play : 1; // UOP 1
unsigned int title_or_time_play : 1; // UOP 0
#else
unsigned int title_or_time_play : 1; // UOP 0
unsigned int chapter_search_or_play : 1; // UOP 1
unsigned int jlc_exists_in_tt_dom : 1;
unsigned int jlc_exists_in_button_cmd : 1;
unsigned int jlc_exists_in_prepost_cmd : 1;
unsigned int jlc_exists_in_cell_cmd : 1;
unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title
unsigned int zero_1 : 1;
#endif
} ATTRIBUTE_PACKED playback_type_t;
/**
* Title Information.
*/
typedef struct {
playback_type_t pb_ty;
uint8_t nr_of_angles;
uint16_t nr_of_ptts;
uint16_t parental_id;
uint8_t title_set_nr;
uint8_t vts_ttn;
uint32_t title_set_sector;
} ATTRIBUTE_PACKED title_info_t;
/**
* PartOfTitle Search Pointer Table.
*/
typedef struct {
uint16_t nr_of_srpts;
uint16_t zero_1;
uint32_t last_byte;
title_info_t *title;
} ATTRIBUTE_PACKED tt_srpt_t;
#define TT_SRPT_SIZE 8
/**
* Parental Management Information Unit Table.
*/
typedef struct {
uint16_t country_code;
uint16_t zero_1;
uint16_t pf_ptl_mai_start_byte;
uint16_t zero_2;
/* uint16_t *pf_ptl_mai // table of nr_of_vtss+1 x 8 */
} ATTRIBUTE_PACKED ptl_mait_country_t;
#define PTL_MAIT_COUNTRY_SIZE 8
/**
* Parental Management Information Table.
*/
typedef struct {
uint16_t nr_of_countries;
uint16_t nr_of_vtss;
uint32_t last_byte;
ptl_mait_country_t *countries;
} ATTRIBUTE_PACKED ptl_mait_t;
#define PTL_MAIT_SIZE 8
/**
* Video Title Set Attributes.
*/
typedef struct {
uint32_t last_byte;
uint32_t vts_cat;
video_attr_t vtsm_vobs_attr;
uint8_t zero_1;
uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1
audio_attr_t vtsm_audio_attr;
audio_attr_t zero_2[7];
uint8_t zero_3[16];
uint8_t zero_4;
uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1
subp_attr_t vtsm_subp_attr;
subp_attr_t zero_5[27];
uint8_t zero_6[2];
video_attr_t vtstt_vobs_video_attr;
uint8_t zero_7;
uint8_t nr_of_vtstt_audio_streams;
audio_attr_t vtstt_audio_attr[8];
uint8_t zero_8[16];
uint8_t zero_9;
uint8_t nr_of_vtstt_subp_streams;
subp_attr_t vtstt_subp_attr[32];
} ATTRIBUTE_PACKED vts_attributes_t;
#define VTS_ATTRIBUTES_SIZE 542
#define VTS_ATTRIBUTES_MIN_SIZE 356
/**
* Video Title Set Attribute Table.
*/
typedef struct {
uint16_t nr_of_vtss;
uint16_t zero_1;
uint32_t last_byte;
vts_attributes_t *vts;
} ATTRIBUTE_PACKED vts_atrt_t;
#define VTS_ATRT_SIZE 8
/**
* Text Data. (Incomplete)
*/
typedef struct {
uint32_t last_byte; /* offsets are relative here */
uint16_t offsets[100]; /* == nr_of_srpts + 1 (first is disc title) */
#if 0
uint16_t unknown; // 0x48 ?? 0x48 words (16bit) info following
uint16_t zero_1;
uint8_t type_of_info;//?? 01 == disc, 02 == Title, 04 == Title part
uint8_t unknown1;
uint8_t unknown2;
uint8_t unknown3;
uint8_t unknown4;//?? allways 0x30 language?, text format?
uint8_t unknown5;
uint16_t offset; // from first
char text[12]; // ended by 0x09
#endif
} ATTRIBUTE_PACKED txtdt_t;
/**
* Text Data Language Unit. (Incomplete)
*/
typedef struct {
uint16_t lang_code;
uint16_t unknown; /* 0x0001, title 1? disc 1? side 1? */
uint32_t txtdt_start_byte; /* prt, rel start of vmg_txtdt_mgi */
txtdt_t *txtdt;
} ATTRIBUTE_PACKED txtdt_lu_t;
#define TXTDT_LU_SIZE 8
/**
* Text Data Manager Information. (Incomplete)
*/
typedef struct {
char disc_name[14]; /* how many bytes?? */
uint16_t nr_of_language_units; /* 32bit?? */
uint32_t last_byte;
txtdt_lu_t *lu;
} ATTRIBUTE_PACKED txtdt_mgi_t;
#define TXTDT_MGI_SIZE 20
/**
* VTS
*
* Structures relating to the Video Title Set (VTS).
*/
/**
* Video Title Set Information Management Table.
*/
typedef struct {
char vts_identifier[12];
uint32_t vts_last_sector;
uint8_t zero_1[12];
uint32_t vtsi_last_sector;
uint8_t zero_2;
uint8_t specification_version;
uint32_t vts_category;
uint16_t zero_3;
uint16_t zero_4;
uint8_t zero_5;
uint8_t zero_6[19];
uint16_t zero_7;
uint8_t zero_8[32];
uint64_t zero_9;
uint8_t zero_10[24];
uint32_t vtsi_last_byte;
uint32_t zero_11;
uint8_t zero_12[56];
uint32_t vtsm_vobs; /* sector */
uint32_t vtstt_vobs; /* sector */
uint32_t vts_ptt_srpt; /* sector */
uint32_t vts_pgcit; /* sector */
uint32_t vtsm_pgci_ut; /* sector */
uint32_t vts_tmapt; /* sector */ // XXX: FIXME TODO Implement
uint32_t vtsm_c_adt; /* sector */
uint32_t vtsm_vobu_admap; /* sector */
uint32_t vts_c_adt; /* sector */
uint32_t vts_vobu_admap; /* sector */
uint8_t zero_13[24];
video_attr_t vtsm_video_attr;
uint8_t zero_14;
uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1
audio_attr_t vtsm_audio_attr;
audio_attr_t zero_15[7];
uint8_t zero_16[17];
uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1
subp_attr_t vtsm_subp_attr;
subp_attr_t zero_17[27];
uint8_t zero_18[2];
video_attr_t vts_video_attr;
uint8_t zero_19;
uint8_t nr_of_vts_audio_streams;
audio_attr_t vts_audio_attr[8];
uint8_t zero_20[17];
uint8_t nr_of_vts_subp_streams;
subp_attr_t vts_subp_attr[32];
/* XXX: how much 'padding' here, if any? */
} ATTRIBUTE_PACKED vtsi_mat_t;
/**
* PartOfTitle Unit Information.
*/
typedef struct {
uint16_t pgcn;
uint16_t pgn;
} ATTRIBUTE_PACKED ptt_info_t;
/**
* PartOfTitle Information.
*/
typedef struct {
uint16_t nr_of_ptts;
ptt_info_t *ptt;
} ATTRIBUTE_PACKED ttu_t;
/**
* PartOfTitle Search Pointer Table.
*/
typedef struct {
uint16_t nr_of_srpts;
uint16_t zero_1;
uint32_t last_byte;
ttu_t *title;
} ATTRIBUTE_PACKED vts_ptt_srpt_t;
#define VTS_PTT_SRPT_SIZE 8
#if PRAGMA_PACK
#pragma pack()
#endif
/**
* The following structure defines an IFO file. The structure is divided into
* two parts, the VMGI, or Video Manager Information, which is read from the
* VIDEO_TS.[IFO,BUP] file, and the VTSI, or Video Title Set Information, which
* is read in from the VTS_XX_0.[IFO,BUP] files.
*/
typedef struct {
dvd_file_t *file;
/* VMGI */
vmgi_mat_t *vmgi_mat;
tt_srpt_t *tt_srpt;
pgc_t *first_play_pgc;
ptl_mait_t *ptl_mait;
vts_atrt_t *vts_atrt;
txtdt_mgi_t *txtdt_mgi;
/* Common */
pgci_ut_t *pgci_ut;
c_adt_t *menu_c_adt;
vobu_admap_t *menu_vobu_admap;
/* VTSI */
vtsi_mat_t *vtsi_mat;
vts_ptt_srpt_t *vts_ptt_srpt;
pgcit_t *vts_pgcit;
int *vts_tmapt; // FIXME add/correct the type
c_adt_t *vts_c_adt;
vobu_admap_t *vts_vobu_admap;
} ifo_handle_t;
#endif /* IFO_TYPES_H_INCLUDED */
--- NEW FILE ---
/*
* Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* Much of the contents in this file is based on VOBDUMP.
*
* VOBDUMP: a program for examining DVD .VOB filse
*
* Copyright 1998, 1999 Eric Smith <eric at brouhaha.com>
*
* VOBDUMP is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. Note that I am not
* granting permission to redistribute or modify VOBDUMP under the
* terms of any later version of the General Public License.
*
* This program is distributed in the hope that it will be useful (or
* at least amusing), but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <inttypes.h>
#include <assert.h>
#include "config.h" // Needed for WORDS_BIGENDIAN
#include "nav_types.h"
#include "nav_print.h"
static void print_time(dvd_time_t *dtime) {
const char *rate;
assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
assert((dtime->frame_u&0xf) < 0xa);
printf("%02x:%02x:%02x.%02x",
dtime->hour,
dtime->minute,
dtime->second,
dtime->frame_u & 0x3f);
switch((dtime->frame_u & 0xc0) >> 6) {
case 1:
rate = "25.00";
break;
case 3:
rate = "29.97";
break;
default:
rate = "(please send a bug report)";
break;
}
printf(" @ %s fps", rate);
}
static void navPrint_PCI_GI(pci_gi_t *pci_gi) {
int i;
printf("pci_gi:\n");
printf("nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn);
printf("vobu_cat 0x%04x\n", pci_gi->vobu_cat);
printf("vobu_uop_ctl 0x%08x\n", *(uint32_t*)&pci_gi->vobu_uop_ctl);
printf("vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm);
printf("vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm);
printf("vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm);
printf("e_eltm ");
print_time(&pci_gi->e_eltm);
printf("\n");
printf("vobu_isrc \"");
for(i = 0; i < 32; i++) {
char c = pci_gi->vobu_isrc[i];
if((c >= ' ') && (c <= '~'))
printf("%c", c);
else
printf(".");
}
printf("\"\n");
}
static void navPrint_NSML_AGLI(nsml_agli_t *nsml_agli) {
int i, j = 0;
for(i = 0; i < 9; i++)
j |= nsml_agli->nsml_agl_dsta[i];
if(j == 0)
return;
printf("nsml_agli:\n");
for(i = 0; i < 9; i++)
if(nsml_agli->nsml_agl_dsta[i])
printf("nsml_agl_c%d_dsta 0x%08x\n", i + 1,
nsml_agli->nsml_agl_dsta[i]);
}
static void navPrint_HL_GI(hl_gi_t *hl_gi, int *btngr_ns, int *btn_ns) {
if((hl_gi->hli_ss & 0x03) == 0)
return;
printf("hl_gi:\n");
printf("hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03);
printf("hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm);
printf("hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm);
printf("btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm);
*btngr_ns = hl_gi->btngr_ns;
printf("btngr_ns %d\n", hl_gi->btngr_ns);
printf("btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty);
printf("btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty);
printf("btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty);
printf("btn_ofn %d\n", hl_gi->btn_ofn);
*btn_ns = hl_gi->btn_ns;
printf("btn_ns %d\n", hl_gi->btn_ns);
printf("nsl_btn_ns %d\n", hl_gi->nsl_btn_ns);
printf("fosl_btnn %d\n", hl_gi->fosl_btnn);
printf("foac_btnn %d\n", hl_gi->foac_btnn);
}
static void navPrint_BTN_COLIT(btn_colit_t *btn_colit) {
int i, j;
j = 0;
for(i = 0; i < 6; i++)
j |= btn_colit->btn_coli[i/2][i&1];
if(j == 0)
return;
printf("btn_colit:\n");
for(i = 0; i < 3; i++)
for(j = 0; j < 2; j++)
printf("btn_cqoli %d %s_coli: %08x\n",
i, (j == 0) ? "sl" : "ac",
btn_colit->btn_coli[i][j]);
}
static void navPrint_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) {
int i, j;
printf("btnit:\n");
printf("btngr_ns: %i\n", btngr_ns);
printf("btn_ns: %i\n", btn_ns);
if(btngr_ns == 0)
return;
for(i = 0; i < btngr_ns; i++) {
for(j = 0; j < (36 / btngr_ns); j++) {
if(j < btn_ns) {
btni_t *btni = &btni_table[(36 / btngr_ns) * i + j];
printf("group %d btni %d: ", i+1, j+1);
printf("btn_coln %d, auto_action_mode %d\n",
btni->btn_coln, btni->auto_action_mode);
printf("coords (%d, %d) .. (%d, %d)\n",
btni->x_start, btni->y_start, btni->x_end, btni->y_end);
printf("up %d, ", btni->up);
printf("down %d, ", btni->down);
printf("left %d, ", btni->left);
printf("right %d\n", btni->right);
// ifoPrint_COMMAND(&btni->cmd);
printf("\n");
}
}
}
}
static void navPrint_HLI(hli_t *hli) {
int btngr_ns = 0, btn_ns = 0;
printf("hli:\n");
navPrint_HL_GI(&hli->hl_gi, & btngr_ns, & btn_ns);
navPrint_BTN_COLIT(&hli->btn_colit);
navPrint_BTNIT(hli->btnit, btngr_ns, btn_ns);
}
void navPrint_PCI(pci_t *pci) {
printf("pci packet:\n");
navPrint_PCI_GI(&pci->pci_gi);
navPrint_NSML_AGLI(&pci->nsml_agli);
navPrint_HLI(&pci->hli);
}
static void navPrint_DSI_GI(dsi_gi_t *dsi_gi) {
printf("dsi_gi:\n");
printf("nv_pck_scr 0x%08x\n", dsi_gi->nv_pck_scr);
printf("nv_pck_lbn 0x%08x\n", dsi_gi->nv_pck_lbn );
printf("vobu_ea 0x%08x\n", dsi_gi->vobu_ea);
printf("vobu_1stref_ea 0x%08x\n", dsi_gi->vobu_1stref_ea);
printf("vobu_2ndref_ea 0x%08x\n", dsi_gi->vobu_2ndref_ea);
printf("vobu_3rdref_ea 0x%08x\n", dsi_gi->vobu_3rdref_ea);
printf("vobu_vob_idn 0x%04x\n", dsi_gi->vobu_vob_idn);
printf("vobu_c_idn 0x%02x\n", dsi_gi->vobu_c_idn);
printf("c_eltm ");
print_time(&dsi_gi->c_eltm);
printf("\n");
}
static void navPrint_SML_PBI(sml_pbi_t *sml_pbi) {
printf("sml_pbi:\n");
printf("category 0x%04x\n", sml_pbi->category);
if(sml_pbi->category & 0x8000)
printf("VOBU is in preunit\n");
if(sml_pbi->category & 0x4000)
printf("VOBU is in ILVU\n");
if(sml_pbi->category & 0x2000)
printf("VOBU at the beginning of ILVU\n");
if(sml_pbi->category & 0x1000)
printf("VOBU at end of PREU of ILVU\n");
printf("ilvu_ea 0x%08x\n", sml_pbi->ilvu_ea);
printf("nxt_ilvu_sa 0x%08x\n", sml_pbi->ilvu_sa);
printf("nxt_ilvu_size 0x%04x\n", sml_pbi->size);
printf("vob_v_s_s_ptm 0x%08x\n", sml_pbi->vob_v_s_s_ptm);
printf("vob_v_e_e_ptm 0x%08x\n", sml_pbi->vob_v_e_e_ptm);
/* $$$ more code needed here */
}
static void navPrint_SML_AGLI(sml_agli_t *sml_agli) {
int i;
printf("sml_agli:\n");
for(i = 0; i < 9; i++) {
printf("agl_c%d address: 0x%08x size 0x%04x\n", i,
sml_agli->data[i].address, sml_agli->data[i].size);
}
}
static void navPrint_VOBU_SRI(vobu_sri_t *vobu_sri) {
int i;
int stime[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11,
10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
printf("vobu_sri:\n");
printf("Next VOBU with Video %08x\n", vobu_sri->next_video);
for(i = 0; i < 19; i++) {
printf("%3.1f %08x ", stime[i]/2.0, vobu_sri->fwda[i]);
}
printf("\n");
printf("Next VOBU %08x\n", vobu_sri->next_vobu);
printf("--\n");
printf("Prev VOBU %08x\n", vobu_sri->prev_vobu);
for(i = 0; i < 19; i++) {
printf("%3.1f %08x ", stime[18 - i]/2.0, vobu_sri->bwda[i]);
}
printf("\n");
printf("Prev VOBU with Video %08x\n", vobu_sri->prev_video);
}
static void navPrint_SYNCI(synci_t *synci) {
int i;
printf("synci:\n");
/* $$$ more code needed here */
for(i = 0; i < 8; i++)
printf("%04x ", synci->a_synca[i]);
for(i = 0; i < 32; i++)
printf("%08x ", synci->sp_synca[i]);
}
void navPrint_DSI(dsi_t *dsi) {
printf("dsi packet:\n");
navPrint_DSI_GI(&dsi->dsi_gi);
navPrint_SML_PBI(&dsi->sml_pbi);
navPrint_SML_AGLI(&dsi->sml_agli);
navPrint_VOBU_SRI(&dsi->vobu_sri);
navPrint_SYNCI(&dsi->synci);
}
--- NEW FILE ---
#ifndef NAV_PRINT_H_INCLUDED
#define NAV_PRINT_H_INCLUDED
/*
* Copyright (C) 2001 Billy Biggs <vektor at dumbterm.net>,
* Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <dvdread/nav_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Prints information contained in the PCI to stdout.
*/
void navPrint_PCI(pci_t *);
/**
* Prints information contained in the DSI to stdout.
*/
void navPrint_DSI(dsi_t *);
#ifdef __cplusplus
};
#endif
#endif /* NAV_PRINT_H_INCLUDED */
--- NEW FILE ---
/*
* Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>
#include "config.h" // Needed for WORDS_BIGENDIAN
#include "bswap.h"
#include "nav_types.h"
#include "nav_read.h"
void navRead_PCI(pci_t *pci, unsigned char *buffer) {
int i, j, k;
assert(sizeof(pci_t) == PCI_BYTES - 1); // -1 for substream id
memcpy(pci, buffer, sizeof(pci_t));
/* Endian conversions */
/* pci pci_gi */
B2N_32(pci->pci_gi.nv_pck_lbn);
B2N_16(pci->pci_gi.vobu_cat);
B2N_32(pci->pci_gi.vobu_s_ptm);
B2N_32(pci->pci_gi.vobu_e_ptm);
B2N_32(pci->pci_gi.vobu_se_e_ptm);
/* pci nsml_agli */
for(i = 0; i < 9; i++)
B2N_32(pci->nsml_agli.nsml_agl_dsta[i]);
/* pci hli hli_gi */
B2N_16(pci->hli.hl_gi.hli_ss);
B2N_32(pci->hli.hl_gi.hli_s_ptm);
B2N_32(pci->hli.hl_gi.hli_e_ptm);
B2N_32(pci->hli.hl_gi.btn_se_e_ptm);
/* pci hli btn_colit */
for(i = 0; i < 3; i++)
for(j = 0; j < 2; j++)
B2N_32(pci->hli.btn_colit.btn_coli[i][j]);
#if !defined(WORDS_BIGENDIAN)
/* pci hli btni */
for(i = 0; i < 36; i++) {
char tmp[6], swap;
memcpy(tmp, &(pci->hli.btnit[i]), 6);
/* This is a B2N_24() */
swap = tmp[0]; tmp[0] = tmp[2]; tmp[2] = swap;
/* This is a B2N_24() */
swap = tmp[3]; tmp[3] = tmp[5]; tmp[5] = swap;
memcpy(&(pci->hli.btnit[i]), tmp, 6);
}
#endif
/* Asserts */
/* pci pci gi */
assert(pci->pci_gi.zero1 == 0);
/* pci hli hli_gi */
assert(pci->hli.hl_gi.zero1 == 0);
assert(pci->hli.hl_gi.zero2 == 0);
assert(pci->hli.hl_gi.zero3 == 0);
assert(pci->hli.hl_gi.zero4 == 0);
assert(pci->hli.hl_gi.zero5 == 0);
/* Are there buttons defined here? */
if((pci->hli.hl_gi.hli_ss & 0x03) != 0) {
assert(pci->hli.hl_gi.btn_ns != 0);
assert(pci->hli.hl_gi.btngr_ns != 0);
} else {
assert((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0)
|| (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0));
}
/* pci hli btnit */
for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) {
for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) {
int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j;
assert(pci->hli.btnit[n].zero1 == 0);
assert(pci->hli.btnit[n].zero2 == 0);
assert(pci->hli.btnit[n].zero3 == 0);
assert(pci->hli.btnit[n].zero4 == 0);
assert(pci->hli.btnit[n].zero5 == 0);
assert(pci->hli.btnit[n].zero6 == 0);
if (j < pci->hli.hl_gi.btn_ns) {
assert(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end);
assert(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end);
assert(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns);
assert(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns);
assert(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns);
assert(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns);
//vmcmd_verify(pci->hli.btnit[n].cmd);
} else {
assert(pci->hli.btnit[n].btn_coln == 0);
assert(pci->hli.btnit[n].auto_action_mode == 0);
assert(pci->hli.btnit[n].x_start == 0);
assert(pci->hli.btnit[n].y_start == 0);
assert(pci->hli.btnit[n].x_end == 0);
assert(pci->hli.btnit[n].y_end == 0);
assert(pci->hli.btnit[n].up == 0);
assert(pci->hli.btnit[n].down == 0);
assert(pci->hli.btnit[n].left == 0);
assert(pci->hli.btnit[n].right == 0);
for (k = 0; k < 8; k++)
assert(pci->hli.btnit[n].cmd.bytes[k] == 0); //CHECK_ZERO?
}
}
}
}
void navRead_DSI(dsi_t *dsi, unsigned char *buffer) {
int i;
assert(sizeof(dsi_t) == DSI_BYTES - 1); // -1 for substream id
memcpy(dsi, buffer, sizeof(dsi_t));
/* Endian conversions */
/* dsi dsi gi */
B2N_32(dsi->dsi_gi.nv_pck_scr);
B2N_32(dsi->dsi_gi.nv_pck_lbn);
B2N_32(dsi->dsi_gi.vobu_ea);
B2N_32(dsi->dsi_gi.vobu_1stref_ea);
B2N_32(dsi->dsi_gi.vobu_2ndref_ea);
B2N_32(dsi->dsi_gi.vobu_3rdref_ea);
B2N_16(dsi->dsi_gi.vobu_vob_idn);
/* dsi sml pbi */
B2N_16(dsi->sml_pbi.category);
B2N_32(dsi->sml_pbi.ilvu_ea);
B2N_32(dsi->sml_pbi.ilvu_sa);
B2N_16(dsi->sml_pbi.size);
B2N_32(dsi->sml_pbi.vob_v_s_s_ptm);
B2N_32(dsi->sml_pbi.vob_v_e_e_ptm);
/* dsi sml agli */
for(i = 0; i < 9; i++) {
B2N_32(dsi->sml_agli.data[ i ].address);
B2N_16(dsi->sml_agli.data[ i ].size);
}
/* dsi vobu sri */
B2N_32(dsi->vobu_sri.next_video);
for(i = 0; i < 19; i++)
B2N_32(dsi->vobu_sri.fwda[i]);
B2N_32(dsi->vobu_sri.next_vobu);
B2N_32(dsi->vobu_sri.prev_vobu);
for(i = 0; i < 19; i++)
B2N_32(dsi->vobu_sri.bwda[i]);
B2N_32(dsi->vobu_sri.prev_video);
/* dsi synci */
for(i = 0; i < 8; i++)
B2N_16(dsi->synci.a_synca[i]);
for(i = 0; i < 32; i++)
B2N_32(dsi->synci.sp_synca[i]);
/* Asserts */
/* dsi dsi gi */
assert(dsi->dsi_gi.zero1 == 0);
}
--- NEW FILE ---
#ifndef NAV_READ_H_INCLUDED
#define NAV_READ_H_INCLUDED
/*
* Copyright (C) 2000, 2001 Håkan Hjort <d95hjort at dtek.chalmers.se>.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <dvdread/nav_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Reads the PCI packet data pointed to into pci struct.
*/
void navRead_PCI(pci_t *, unsigned char *);
/**
* Reads the DSI packet data pointed to into dsi struct.
*/
void navRead_DSI(dsi_t *, unsigned char *);
#ifdef __cplusplus
};
#endif
#endif /* NAV_READ_H_INCLUDED */
--- NEW FILE ---
#ifndef NAV_TYPES_H_INCLUDED
#define NAV_TYPES_H_INCLUDED
/*
* Copyright (C) 2000, 2001 Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* The data structures in this file should represent the layout of the
* pci and dsi packets as they are stored in the stream. Information
* found by reading the source to VOBDUMP is the base for the structure
* and names of these data types.
*
* VOBDUMP: a program for examining DVD .VOB files.
* Copyright 1998, 1999 Eric Smith <eric at brouhaha.com>
*
* VOBDUMP is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. Note that I am not
* granting permission to redistribute or modify VOBDUMP under the terms
* of any later version of the General Public License.
*
* This program is distributed in the hope that it will be useful (or at
* least amusing), but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <inttypes.h>
#include <dvdread/ifo_types.h> // only dvd_time_t, vm_cmd_t and user_ops_t
#undef ATTRIBUTE_PACKED
#undef PRAGMA_PACK_BEGIN
#undef PRAGMA_PACK_END
#if defined(__GNUC__)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
#define ATTRIBUTE_PACKED __attribute__ ((packed))
#define PRAGMA_PACK 0
#endif
#endif
#if !defined(ATTRIBUTE_PACKED)
#define ATTRIBUTE_PACKED
#define PRAGMA_PACK 1
#endif
/* The length including the substream id byte. */
#define PCI_BYTES 0x3d4
#define DSI_BYTES 0x3fa
#define PS2_PCI_SUBSTREAM_ID 0x00
#define PS2_DSI_SUBSTREAM_ID 0x01
/* Remove this */
#define DSI_START_BYTE 1031
#if PRAGMA_PACK
#pragma pack(1)
#endif
/**
* PCI General Information
*/
typedef struct {
uint32_t nv_pck_lbn;
uint16_t vobu_cat;
uint16_t zero1;
user_ops_t vobu_uop_ctl;
uint32_t vobu_s_ptm;
uint32_t vobu_e_ptm;
uint32_t vobu_se_e_ptm;
dvd_time_t e_eltm;
char vobu_isrc[32];
} ATTRIBUTE_PACKED pci_gi_t;
/**
* Non Seamless Angle Information
*/
typedef struct {
uint32_t nsml_agl_dsta[9];
} ATTRIBUTE_PACKED nsml_agli_t;
/**
* Highlight General Information
*/
typedef struct {
uint16_t hli_ss; ///< only low 2 bits
uint32_t hli_s_ptm;
uint32_t hli_e_ptm;
uint32_t btn_se_e_ptm;
#ifdef WORDS_BIGENDIAN
unsigned int zero1 : 2;
unsigned int btngr_ns : 2;
unsigned int zero2 : 1;
unsigned int btngr1_dsp_ty : 3;
unsigned int zero3 : 1;
unsigned int btngr2_dsp_ty : 3;
unsigned int zero4 : 1;
unsigned int btngr3_dsp_ty : 3;
#else
unsigned int btngr1_dsp_ty : 3;
unsigned int zero2 : 1;
unsigned int btngr_ns : 2;
unsigned int zero1 : 2;
unsigned int btngr3_dsp_ty : 3;
unsigned int zero4 : 1;
unsigned int btngr2_dsp_ty : 3;
unsigned int zero3 : 1;
#endif
uint8_t btn_ofn;
uint8_t btn_ns; ///< only low 6 bits
uint8_t nsl_btn_ns; ///< only low 6 bits
uint8_t zero5;
uint8_t fosl_btnn; ///< only low 6 bits
uint8_t foac_btnn; ///< only low 6 bits
} ATTRIBUTE_PACKED hl_gi_t;
/**
* Button Color Information Table
*/
typedef struct {
uint32_t btn_coli[3][2];
} ATTRIBUTE_PACKED btn_colit_t;
/**
* Button Information
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int btn_coln : 2;
unsigned int x_start : 10;
unsigned int zero1 : 2;
unsigned int x_end : 10;
unsigned int auto_action_mode : 2;
unsigned int y_start : 10;
unsigned int zero2 : 2;
unsigned int y_end : 10;
unsigned int zero3 : 2;
unsigned int up : 6;
unsigned int zero4 : 2;
unsigned int down : 6;
unsigned int zero5 : 2;
unsigned int left : 6;
unsigned int zero6 : 2;
unsigned int right : 6;
#else
unsigned int x_end : 10;
unsigned int zero1 : 2;
unsigned int x_start : 10;
unsigned int btn_coln : 2;
unsigned int y_end : 10;
unsigned int zero2 : 2;
unsigned int y_start : 10;
unsigned int auto_action_mode : 2;
unsigned int up : 6;
unsigned int zero3 : 2;
unsigned int down : 6;
unsigned int zero4 : 2;
unsigned int left : 6;
unsigned int zero5 : 2;
unsigned int right : 6;
unsigned int zero6 : 2;
#endif
vm_cmd_t cmd;
} ATTRIBUTE_PACKED btni_t;
/**
* Highlight Information
*/
typedef struct {
hl_gi_t hl_gi;
btn_colit_t btn_colit;
btni_t btnit[36];
} ATTRIBUTE_PACKED hli_t;
/**
* PCI packet
*/
typedef struct {
pci_gi_t pci_gi;
nsml_agli_t nsml_agli;
hli_t hli;
uint8_t zero1[189];
} ATTRIBUTE_PACKED pci_t;
/**
* DSI General Information
*/
typedef struct {
uint32_t nv_pck_scr;
uint32_t nv_pck_lbn;
uint32_t vobu_ea;
uint32_t vobu_1stref_ea;
uint32_t vobu_2ndref_ea;
uint32_t vobu_3rdref_ea;
uint16_t vobu_vob_idn;
uint8_t zero1;
uint8_t vobu_c_idn;
dvd_time_t c_eltm;
} ATTRIBUTE_PACKED dsi_gi_t;
/**
* Seamless Playback Information
*/
typedef struct {
uint16_t category; ///< category of seamless VOBU
uint32_t ilvu_ea; ///< end address of interleaved Unit (sectors)
uint32_t ilvu_sa; ///< start address of next interleaved unit (sectors)
uint16_t size; ///< size of next interleaved unit (sectors)
uint32_t vob_v_s_s_ptm; ///< video start ptm in vob
uint32_t vob_v_e_e_ptm; ///< video end ptm in vob
struct {
uint32_t stp_ptm1;
uint32_t stp_ptm2;
uint32_t gap_len1;
uint32_t gap_len2;
} vob_a[8];
} ATTRIBUTE_PACKED sml_pbi_t;
/**
* Seamless Angle Infromation for one angle
*/
typedef struct {
uint32_t address; ///< Sector offset to next ILVU, high bit is before/after
uint16_t size; ///< Byte size of the ILVU poited to by address.
} ATTRIBUTE_PACKED sml_agl_data_t;
/**
* Seamless Angle Infromation
*/
typedef struct {
sml_agl_data_t data[9];
} ATTRIBUTE_PACKED sml_agli_t;
/**
* VOBU Search Information
*/
typedef struct {
uint32_t next_video; ///< Next vobu that contains video
uint32_t fwda[19]; ///< Forwards, time
uint32_t next_vobu;
uint32_t prev_vobu;
uint32_t bwda[19]; ///< Backwards, time
uint32_t prev_video;
} ATTRIBUTE_PACKED vobu_sri_t;
#define SRI_END_OF_CELL 0x3fffffff
/**
* Synchronous Information
*/
typedef struct {
uint16_t a_synca[8]; ///< Sector offset to first audio packet for this VOBU
uint32_t sp_synca[32]; ///< Sector offset to first subpicture packet
} ATTRIBUTE_PACKED synci_t;
/**
* DSI packet
*/
typedef struct {
dsi_gi_t dsi_gi;
sml_pbi_t sml_pbi;
sml_agli_t sml_agli;
vobu_sri_t vobu_sri;
synci_t synci;
uint8_t zero1[471];
} ATTRIBUTE_PACKED dsi_t;
#if PRAGMA_PACK
#pragma pack()
#endif
#endif /* NAV_TYPES_H_INCLUDED */
More information about the MPlayer-cvslog
mailing list