📄 dvd_reader.c
字号:
/*
* Copyright (C) 2001, 2002, 2003 Billy Biggs <vektor@dumbterm.net>,
* H錵an Hjort <d95hjort@dtek.chalmers.se>,
* Bj鰎n Englund <d4bjorn@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 "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include "dvdcss/dvdcss.h"
#include "dvd_udf.h"
#include "dvd_reader.h"
#include "md5.h"
#define DEFAULT_UDF_CACHE_LEVEL 1
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. */
dvdcss_t fd;
/* Information required for a directory path drive. */
char *path_root;
/* Filesystem cache */
int udfcache_level; /* 0 - turned off, 1 - on */
void *udfcache;
};
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 ];
dvdcss_handle title_devs[ 9 ];
/* Calculated at open-time, size in blocks. */
int filesize;
};
/**
* Set the level of caching on udf
* level = 0 (no caching)
* level = 1 (caching filesystem info)
*/
int DVDUDFCacheLevel(dvd_reader_t *device, int level)
{
struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
if(level > 0) {
level = 1;
} else if(level < 0) {
return dev->udfcache_level;
}
dev->udfcache_level = level;
return level;
}
void *GetUDFCacheHandle(dvd_reader_t *device)
{
struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
return dev->udfcache;
}
void SetUDFCacheHandle(dvd_reader_t *device, void *cache)
{
struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
dev->udfcache = cache;
}
/**
* Close a DVD block device file.
*/
void DVDClose( dvd_reader_t *dvd )
{
if( dvd ) {
if( dvd->fd ) dvdcss_close( dvd->fd );
if( dvd->path_root ) free( dvd->path_root );
free( dvd );
}
}
/**
* Open a DVD block device file.
*/
dvd_reader_t *DVDOpen( const char *location )
{
dvd_reader_t *dvd;
dvdcss_t dev;
dev= dvdcss_open((char*)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 NULL;
dvd->isImageFile = 1;
dvd->fd = dev;
dvd->path_root = 0;
dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
dvd->udfcache = NULL;
/* 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. */
dvd->css_title = 0;
return dvd;
}
/**
* Open an unencrypted file on a DVD image file.
*/
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;
dvd_file->title_sizes[ 0 ]= len / DVD_VIDEO_LB_LEN;
dvd_file->title_devs[ 0 ]= dvd->fd;
return dvd_file;
}
/* 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;
char *nokeys_str = getenv("DVDREAD_NOKEYS");
if(nokeys_str != NULL)
return 0;
//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( dvdcss_title( dvd->fd, (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 ) 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( dvdcss_title( dvd->fd, (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 an vob file on a DVD.
*/
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_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
filename );
}
*/
return dvd_file;
}
/* Private */
int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -