initial commit
This commit is contained in:
parent
7c99758cad
commit
be4930a8a3
16 changed files with 3329 additions and 0 deletions
344
dvd_reader.h
Normal file
344
dvd_reader.h
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
|
||||
* Håkan Hjort <d95hjort@dtek.chalmers.se>,
|
||||
* Björn Englund <d4bjorn@dtek.chalmers.se>
|
||||
*
|
||||
* This file is part of libdvdread.
|
||||
*
|
||||
* libdvdread 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.
|
||||
*
|
||||
* libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The DVD access interface.
|
||||
*
|
||||
* This file contains the functions that form the interface to to
|
||||
* reading files located on a DVD.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The current version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The length of one Logical Block of a DVD.
|
||||
*/
|
||||
#define DVD_VIDEO_LB_LEN 2048
|
||||
|
||||
/**
|
||||
* Maximum length of filenames allowed in UDF.
|
||||
*/
|
||||
#define MAX_UDF_FILE_NAME_LEN 2048
|
||||
|
||||
typedef long int off_t;
|
||||
|
||||
/**
|
||||
* Opaque type that is used as a handle for one instance of an opened DVD.
|
||||
*/
|
||||
typedef struct dvd_reader_s dvd_reader_t;
|
||||
typedef struct dvd_reader_device_s dvd_reader_device_t;
|
||||
|
||||
/**
|
||||
* Opaque type for a file read handle, much like a normal fd or FILE *.
|
||||
*/
|
||||
typedef struct dvd_file_s dvd_file_t;
|
||||
|
||||
struct dvd_reader_stream_cb
|
||||
{
|
||||
int ( *pf_seek ) ( void *p_stream, uint64_t i_pos);
|
||||
int ( *pf_read ) ( void *p_stream, void* buffer, int i_read);
|
||||
int ( *pf_readv ) ( void *p_stream, void *p_iovec, int i_blocks);
|
||||
};
|
||||
typedef struct dvd_reader_stream_cb dvd_reader_stream_cb;
|
||||
|
||||
/**
|
||||
* Custom logger callback for DVDOpen[Stream]2
|
||||
* @param private Handle as provided in Open functions
|
||||
* @param level Log level
|
||||
* @param fmt Format string
|
||||
* @param args Arguments list
|
||||
* pf_log(priv, level, fmt, args);
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
DVD_LOGGER_LEVEL_INFO,
|
||||
DVD_LOGGER_LEVEL_ERROR,
|
||||
DVD_LOGGER_LEVEL_WARN,
|
||||
DVD_LOGGER_LEVEL_DEBUG,
|
||||
} dvd_logger_level_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// void ( *pf_log ) ( void *, dvd_logger_level_t, const char *, va_list );
|
||||
void *pf_log;
|
||||
} dvd_logger_cb;
|
||||
|
||||
/**
|
||||
* Public type that is used to provide statistics on a handle.
|
||||
*/
|
||||
typedef struct {
|
||||
off_t size; /**< Total size of file in bytes */
|
||||
int nr_parts; /**< Number of file parts */
|
||||
off_t parts_size[9]; /**< Size of each part in bytes */
|
||||
} dvd_stat_t;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* The second form of Open function (DVDOpenStream) can be used to
|
||||
* provide custom stream_cb functions to access the DVD (see libdvdcss).
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* @param path Specifies the the device, file or directory to be used.
|
||||
* @param stream is a private handle used by stream_cb
|
||||
* @param stream_cb is a struct containing seek and read functions
|
||||
* @return If successful a a read handle is returned. Otherwise 0 is returned.
|
||||
*
|
||||
* dvd = DVDOpen(path);
|
||||
* dvd = DVDOpenStream(stream, &stream_cb);
|
||||
*/
|
||||
dvd_reader_t *DVDOpen( const char * );
|
||||
dvd_reader_t *DVDOpenStream( void *, dvd_reader_stream_cb * );
|
||||
|
||||
/**
|
||||
* Same as DVDOpen, but with private handle to be passed back on callbacks
|
||||
*
|
||||
* @param path Specifies the the device, file or directory to be used.
|
||||
* @param priv is a private handle
|
||||
* @param logcb is a custom logger callback struct, or NULL if none needed
|
||||
* @param stream_cb is a struct containing seek and read functions
|
||||
* @return If successful a a read handle is returned. Otherwise 0 is returned.
|
||||
*
|
||||
* dvd = DVDOpen2(priv, logcb, path);
|
||||
* dvd = DVDOpenStream2(priv, logcb, &stream_cb);
|
||||
*/
|
||||
dvd_reader_t *DVDOpen2( void *, const dvd_logger_cb *, const char * );
|
||||
dvd_reader_t *DVDOpenStream2( void *, const dvd_logger_cb *, dvd_reader_stream_cb * );
|
||||
|
||||
/**
|
||||
* Closes and cleans up the DVD reader object.
|
||||
*
|
||||
* You must close all open files before calling this function.
|
||||
*
|
||||
* @param dvd A read handle that should be closed.
|
||||
*
|
||||
* DVDClose(dvd);
|
||||
*/
|
||||
void DVDClose( dvd_reader_t * );
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
DVD_READ_INFO_FILE, /**< VIDEO_TS.IFO or VTS_XX_0.IFO (title) */
|
||||
DVD_READ_INFO_BACKUP_FILE, /**< VIDEO_TS.BUP or VTS_XX_0.BUP (title) */
|
||||
DVD_READ_MENU_VOBS, /**< VIDEO_TS.VOB or VTS_XX_0.VOB (title) */
|
||||
DVD_READ_TITLE_VOBS /**< VTS_XX_[1-9].VOB (title). All files in
|
||||
the title set are opened and read as a
|
||||
single file. */
|
||||
} dvd_read_domain_t;
|
||||
|
||||
/**
|
||||
* Stats a file on the DVD given the title number and domain.
|
||||
* The information about the file is stored in a dvd_stat_t
|
||||
* which contains information about the size of the file and
|
||||
* the number of parts in case of a multipart file and the respective
|
||||
* sizes of the parts.
|
||||
* A multipart file is for instance VTS_02_1.VOB, VTS_02_2.VOB, VTS_02_3.VOB
|
||||
* The size of VTS_02_1.VOB will be stored in stat->parts_size[0],
|
||||
* VTS_02_2.VOB in stat->parts_size[1], ...
|
||||
* The total size (sum of all parts) is stored in stat->size and
|
||||
* stat->nr_parts will hold the number of parts.
|
||||
* Only DVD_READ_TITLE_VOBS (VTS_??_[1-9].VOB) can be multipart files.
|
||||
*
|
||||
* This function is only of use if you want to get the size of each file
|
||||
* in the filesystem. These sizes are not needed to use any other
|
||||
* functions in libdvdread.
|
||||
*
|
||||
* @param dvd A dvd read handle.
|
||||
* @param titlenum Which Video Title Set should be used, VIDEO_TS is 0.
|
||||
* @param domain Which domain.
|
||||
* @param stat Pointer to where the result is stored.
|
||||
* @return If successful 0, otherwise -1.
|
||||
*
|
||||
* int DVDFileStat(dvd, titlenum, domain, stat);
|
||||
*/
|
||||
int DVDFileStat(dvd_reader_t *, int, dvd_read_domain_t, dvd_stat_t *);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param dvd A dvd read handle.
|
||||
* @param titlenum Which Video Title Set should be used, VIDEO_TS is 0.
|
||||
* @param domain Which domain.
|
||||
* @return If successful a a file read handle is returned, otherwise 0.
|
||||
*
|
||||
* dvd_file = DVDOpenFile(dvd, titlenum, domain); */
|
||||
dvd_file_t *DVDOpenFile( dvd_reader_t *, int, dvd_read_domain_t );
|
||||
|
||||
/**
|
||||
* Closes a file and frees the associated structure.
|
||||
*
|
||||
* @param dvd_file The file read handle to be closed.
|
||||
*
|
||||
* DVDCloseFile(dvd_file);
|
||||
*/
|
||||
void DVDCloseFile( dvd_file_t * );
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param dvd_file A file read handle.
|
||||
* @param offset Block offset from the start of the file to start reading at.
|
||||
* @param block_count Number of block to read.
|
||||
* @param data Pointer to a buffer to write the data into.
|
||||
* @return Returns number of blocks read on success, -1 on error.
|
||||
*
|
||||
* blocks_read = DVDReadBlocks(dvd_file, offset, block_count, data);
|
||||
*/
|
||||
ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * );
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param dvd_file A file read handle.
|
||||
* @param seek_offset Byte offset from the start of the file to seek to.
|
||||
* @return The resulting position in bytes from the beginning of the file.
|
||||
*
|
||||
* offset_set = DVDFileSeek(dvd_file, seek_offset);
|
||||
*/
|
||||
int32_t DVDFileSeek( dvd_file_t *, int32_t );
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param dvd_file A file read handle.
|
||||
* @param data Pointer to a buffer to write the data into.
|
||||
* @param bytes Number of bytes to read.
|
||||
* @return Returns number of bytes read on success, -1 on error.
|
||||
*
|
||||
* bytes_read = DVDReadBytes(dvd_file, data, bytes);
|
||||
*/
|
||||
ssize_t DVDReadBytes( dvd_file_t *, void *, size_t );
|
||||
|
||||
/**
|
||||
* Returns the file size in blocks.
|
||||
*
|
||||
* @param dvd_file A file read handle.
|
||||
* @return The size of the file in blocks, -1 on error.
|
||||
*
|
||||
* blocks = DVDFileSize(dvd_file);
|
||||
*/
|
||||
ssize_t DVDFileSize( dvd_file_t * );
|
||||
|
||||
/**
|
||||
* Get a unique 128 bit disc ID.
|
||||
* This is the MD5 sum of VIDEO_TS.IFO and the VTS_0?_0.IFO files
|
||||
* in title order (those that exist).
|
||||
* If you need a 'text' representation of the id, print it as a
|
||||
* hexadecimal number, using lowercase letters, discid[0] first.
|
||||
* I.e. the same format as the command-line 'md5sum' program uses.
|
||||
*
|
||||
* @param dvd A read handle to get the disc ID from
|
||||
* @param discid The buffer to put the disc ID into. The buffer must
|
||||
* have room for 128 bits (16 chars).
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int DVDDiscID( dvd_reader_t *, unsigned char * );
|
||||
|
||||
/**
|
||||
* Get the UDF VolumeIdentifier and VolumeSetIdentifier
|
||||
* from the PrimaryVolumeDescriptor.
|
||||
*
|
||||
* @param dvd A read handle to get the disc ID from
|
||||
* @param volid The buffer to put the VolumeIdentifier into.
|
||||
* The VolumeIdentifier is latin-1 encoded (8bit unicode)
|
||||
* null terminated and max 32 bytes (including '\0')
|
||||
* @param volid_size No more than volid_size bytes will be copied to volid.
|
||||
* If the VolumeIdentifier is truncated because of this
|
||||
* it will still be null terminated.
|
||||
* @param volsetid The buffer to put the VolumeSetIdentifier into.
|
||||
* The VolumeIdentifier is 128 bytes as
|
||||
* stored in the UDF PrimaryVolumeDescriptor.
|
||||
* Note that this is not a null terminated string.
|
||||
* @param volsetid_size At most volsetid_size bytes will be copied to volsetid.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int,
|
||||
unsigned char *, unsigned int );
|
||||
|
||||
int DVDFileSeekForce( dvd_file_t *, int offset, int force_size);
|
||||
|
||||
/**
|
||||
* Get the ISO9660 VolumeIdentifier and VolumeSetIdentifier
|
||||
*
|
||||
* * Only use this function as fallback if DVDUDFVolumeInfo returns 0 *
|
||||
* * this will happen on a disc mastered only with a iso9660 filesystem *
|
||||
* * All video DVD discs have UDF filesystem *
|
||||
*
|
||||
* @param dvd A read handle to get the disc ID from
|
||||
* @param volid The buffer to put the VolumeIdentifier into.
|
||||
* The VolumeIdentifier is coded with '0-9','A-Z','_'
|
||||
* null terminated and max 33 bytes (including '\0')
|
||||
* @param volid_size No more than volid_size bytes will be copied to volid.
|
||||
* If the VolumeIdentifier is truncated because of this
|
||||
* it will still be null terminated.
|
||||
* @param volsetid The buffer to put the VolumeSetIdentifier into.
|
||||
* The VolumeIdentifier is 128 bytes as
|
||||
* stored in the ISO9660 PrimaryVolumeDescriptor.
|
||||
* Note that this is not a null terminated string.
|
||||
* @param volsetid_size At most volsetid_size bytes will be copied to volsetid.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int,
|
||||
unsigned char *, unsigned int );
|
||||
|
||||
/**
|
||||
* Sets the level of caching that is done when reading from a device
|
||||
*
|
||||
* @param dvd A read handle to get the disc ID from
|
||||
* @param level The level of caching wanted.
|
||||
* -1 - returns the current setting.
|
||||
* 0 - UDF Cache turned off.
|
||||
* 1 - (default level) Pointers to IFO files and some data from
|
||||
* PrimaryVolumeDescriptor are cached.
|
||||
*
|
||||
* @return The level of caching.
|
||||
*/
|
||||
int DVDUDFCacheLevel( dvd_reader_t *, int );
|
38
dvd_ripper.py
Normal file
38
dvd_ripper.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
import cffi
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from dvdnav import DVDNav
|
||||
from dvdread import DVDRead
|
||||
import subprocess as SP
|
||||
import json
|
||||
from vob_demux import demux
|
||||
from ff_d2v import make_d2v
|
||||
def loadlib(dll_path,*includes,**kwargs):
|
||||
ffi = cffi.FFI()
|
||||
for include in includes:
|
||||
ffi.cdef(open(include).read(),kwargs)
|
||||
return ffi,ffi.dlopen(dll_path)
|
||||
|
||||
os.environ["DVDCSS_VERBOSE"]="2"
|
||||
os.environ["DVDCSS_METHOD"]="disc"
|
||||
|
||||
r=DVDRead(sys.argv[1])
|
||||
out_folder=os.path.join("out","_".join([r.disc_id,r.udf_disc_name or r.iso_disc_name]).replace(" ","_"))
|
||||
del r
|
||||
os.makedirs(out_folder,exist_ok=True)
|
||||
d=DVDNav(sys.argv[1])
|
||||
for k,v in d.titles.items():
|
||||
v['duration']=v['duration'].total_seconds()
|
||||
v['chapters']=[c.total_seconds() for c in v['chapters']]
|
||||
d.titles[k]=v
|
||||
with open(os.path.join(out_folder,f"{k}.json"),"w") as fh:
|
||||
json.dump(v,fh)
|
||||
for a in range(v['angles']):
|
||||
a+=1
|
||||
outfile=os.path.join(out_folder,f"{k}_{a}.vob")
|
||||
with open(outfile,"wb") as fh:
|
||||
for block in d.get_blocks(k,a):
|
||||
fh.write(block)
|
||||
demux(outfile)
|
||||
os.unlink(outfile)
|
266
dvd_types.h
Normal file
266
dvd_types.h
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001 Björn Englund, Håkan Hjort
|
||||
*
|
||||
* This file is part of libdvdnav, a DVD navigation library. It is a modified
|
||||
* file originally part of the Ogle DVD player project.
|
||||
*
|
||||
* libdvdnav 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.
|
||||
*
|
||||
* libdvdnav 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 libdvdnav; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Various useful structs and enums for DVDs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DVD Menu ID
|
||||
* (see dvdnav_menu_call())
|
||||
*/
|
||||
typedef enum {
|
||||
/* When used in VTS domain, DVD_MENU_Escape behaves like DVD_MENU_Root,
|
||||
* but from within a menu domain, DVD_MENU_Escape resumes playback. */
|
||||
DVD_MENU_Escape = 0,
|
||||
DVD_MENU_Title = 2,
|
||||
DVD_MENU_Root = 3,
|
||||
DVD_MENU_Subpicture = 4,
|
||||
DVD_MENU_Audio = 5,
|
||||
DVD_MENU_Angle = 6,
|
||||
DVD_MENU_Part = 7
|
||||
} DVDMenuID_t;
|
||||
|
||||
/* Domain */
|
||||
typedef enum {
|
||||
DVD_DOMAIN_FirstPlay = 1, /* First Play Domain */
|
||||
DVD_DOMAIN_VTSTitle = 2, /* Video Title Set Domain */
|
||||
DVD_DOMAIN_VMGM = 4, /* Video Manager Domain */
|
||||
DVD_DOMAIN_VTSMenu = 8 /* Video Title Set Menu Domain */
|
||||
} DVDDomain_t;
|
||||
|
||||
/*
|
||||
* Structure containing info on highlight areas
|
||||
* (see dvdnav_get_highlight_area())
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t palette; /* The CLUT entries for the highlight palette
|
||||
(4-bits per entry -> 4 entries) */
|
||||
uint16_t sx,sy,ex,ey; /* The start/end x,y positions */
|
||||
uint32_t pts; /* Highlight PTS to match with SPU */
|
||||
|
||||
/* button number for the SPU decoder/overlaying engine */
|
||||
uint32_t buttonN;
|
||||
} dvdnav_highlight_area_t;
|
||||
|
||||
/* The audio format */
|
||||
typedef enum {
|
||||
DVD_AUDIO_FORMAT_AC3 = 0,
|
||||
DVD_AUDIO_FORMAT_UNKNOWN_1 = 1,
|
||||
DVD_AUDIO_FORMAT_MPEG = 2,
|
||||
DVD_AUDIO_FORMAT_MPEG2_EXT = 3,
|
||||
DVD_AUDIO_FORMAT_LPCM = 4,
|
||||
DVD_AUDIO_FORMAT_UNKNOWN_5 = 5,
|
||||
DVD_AUDIO_FORMAT_DTS = 6,
|
||||
DVD_AUDIO_FORMAT_SDDS = 7
|
||||
} DVDAudioFormat_t;
|
||||
|
||||
/* the following types are currently unused */
|
||||
|
||||
// #if 0
|
||||
|
||||
// /* User operation permissions */
|
||||
// typedef enum {
|
||||
// UOP_FLAG_TitleOrTimePlay = 0x00000001,
|
||||
// UOP_FLAG_ChapterSearchOrPlay = 0x00000002,
|
||||
// UOP_FLAG_TitlePlay = 0x00000004,
|
||||
// UOP_FLAG_Stop = 0x00000008,
|
||||
// UOP_FLAG_GoUp = 0x00000010,
|
||||
// UOP_FLAG_TimeOrChapterSearch = 0x00000020,
|
||||
// UOP_FLAG_PrevOrTopPGSearch = 0x00000040,
|
||||
// UOP_FLAG_NextPGSearch = 0x00000080,
|
||||
// UOP_FLAG_ForwardScan = 0x00000100,
|
||||
// UOP_FLAG_BackwardScan = 0x00000200,
|
||||
// UOP_FLAG_TitleMenuCall = 0x00000400,
|
||||
// UOP_FLAG_RootMenuCall = 0x00000800,
|
||||
// UOP_FLAG_SubPicMenuCall = 0x00001000,
|
||||
// UOP_FLAG_AudioMenuCall = 0x00002000,
|
||||
// UOP_FLAG_AngleMenuCall = 0x00004000,
|
||||
// UOP_FLAG_ChapterMenuCall = 0x00008000,
|
||||
// UOP_FLAG_Resume = 0x00010000,
|
||||
// UOP_FLAG_ButtonSelectOrActivate = 0x00020000,
|
||||
// UOP_FLAG_StillOff = 0x00040000,
|
||||
// UOP_FLAG_PauseOn = 0x00080000,
|
||||
// UOP_FLAG_AudioStreamChange = 0x00100000,
|
||||
// UOP_FLAG_SubPicStreamChange = 0x00200000,
|
||||
// UOP_FLAG_AngleChange = 0x00400000,
|
||||
// UOP_FLAG_KaraokeAudioPresModeChange = 0x00800000,
|
||||
// UOP_FLAG_VideoPresModeChange = 0x01000000
|
||||
// } DVDUOP_t;
|
||||
|
||||
// /* Parental Level */
|
||||
// typedef enum {
|
||||
// DVD_PARENTAL_LEVEL_1 = 1,
|
||||
// DVD_PARENTAL_LEVEL_2 = 2,
|
||||
// DVD_PARENTAL_LEVEL_3 = 3,
|
||||
// DVD_PARENTAL_LEVEL_4 = 4,
|
||||
// DVD_PARENTAL_LEVEL_5 = 5,
|
||||
// DVD_PARENTAL_LEVEL_6 = 6,
|
||||
// DVD_PARENTAL_LEVEL_7 = 7,
|
||||
// DVD_PARENTAL_LEVEL_8 = 8,
|
||||
// DVD_PARENTAL_LEVEL_None = 15
|
||||
// } DVDParentalLevel_t;
|
||||
|
||||
// /* Language ID (ISO-639 language code) */
|
||||
// typedef uint16_t DVDLangID_t;
|
||||
|
||||
// /* Country ID (ISO-3166 country code) */
|
||||
// typedef uint16_t DVDCountryID_t;
|
||||
|
||||
// /* Register */
|
||||
// typedef uint16_t DVDRegister_t;
|
||||
// typedef enum {
|
||||
// DVDFalse = 0,
|
||||
// DVDTrue = 1
|
||||
// } DVDBool_t;
|
||||
// typedef DVDRegister_t DVDGPRMArray_t[16];
|
||||
// typedef DVDRegister_t DVDSPRMArray_t[24];
|
||||
|
||||
// /* Navigation */
|
||||
// typedef int DVDStream_t;
|
||||
// typedef int DVDPTT_t;
|
||||
// typedef int DVDTitle_t;
|
||||
|
||||
// /* Angle number (1-9 or default?) */
|
||||
// typedef int DVDAngle_t;
|
||||
|
||||
// /* Timecode */
|
||||
// typedef struct {
|
||||
// uint8_t Hours;
|
||||
// uint8_t Minutes;
|
||||
// uint8_t Seconds;
|
||||
// uint8_t Frames;
|
||||
// } DVDTimecode_t;
|
||||
|
||||
// /* Subpicture stream number (0-31,62,63) */
|
||||
// typedef int DVDSubpictureStream_t;
|
||||
|
||||
// /* Audio stream number (0-7, 15(none)) */
|
||||
// typedef int DVDAudioStream_t;
|
||||
|
||||
// /* The audio application mode */
|
||||
// typedef enum {
|
||||
// DVD_AUDIO_APP_MODE_None = 0,
|
||||
// DVD_AUDIO_APP_MODE_Karaoke = 1,
|
||||
// DVD_AUDIO_APP_MODE_Surround = 2,
|
||||
// DVD_AUDIO_APP_MODE_Other = 3
|
||||
// } DVDAudioAppMode_t;
|
||||
|
||||
// /* Audio language extension */
|
||||
// typedef enum {
|
||||
// DVD_AUDIO_LANG_EXT_NotSpecified = 0,
|
||||
// DVD_AUDIO_LANG_EXT_NormalCaptions = 1,
|
||||
// DVD_AUDIO_LANG_EXT_VisuallyImpaired = 2,
|
||||
// DVD_AUDIO_LANG_EXT_DirectorsComments1 = 3,
|
||||
// DVD_AUDIO_LANG_EXT_DirectorsComments2 = 4
|
||||
// } DVDAudioLangExt_t;
|
||||
|
||||
// /* Subpicture language extension */
|
||||
// typedef enum {
|
||||
// DVD_SUBPICTURE_LANG_EXT_NotSpecified = 0,
|
||||
// DVD_SUBPICTURE_LANG_EXT_NormalCaptions = 1,
|
||||
// DVD_SUBPICTURE_LANG_EXT_BigCaptions = 2,
|
||||
// DVD_SUBPICTURE_LANG_EXT_ChildrensCaptions = 3,
|
||||
// DVD_SUBPICTURE_LANG_EXT_NormalCC = 5,
|
||||
// DVD_SUBPICTURE_LANG_EXT_BigCC = 6,
|
||||
// DVD_SUBPICTURE_LANG_EXT_ChildrensCC = 7,
|
||||
// DVD_SUBPICTURE_LANG_EXT_Forced = 9,
|
||||
// DVD_SUBPICTURE_LANG_EXT_NormalDirectorsComments = 13,
|
||||
// DVD_SUBPICTURE_LANG_EXT_BigDirectorsComments = 14,
|
||||
// DVD_SUBPICTURE_LANG_EXT_ChildrensDirectorsComments = 15,
|
||||
// } DVDSubpictureLangExt_t;
|
||||
|
||||
// /* Karaoke Downmix mode */
|
||||
// typedef enum {
|
||||
// DVD_KARAOKE_DOWNMIX_0to0 = 0x0001,
|
||||
// DVD_KARAOKE_DOWNMIX_1to0 = 0x0002,
|
||||
// DVD_KARAOKE_DOWNMIX_2to0 = 0x0004,
|
||||
// DVD_KARAOKE_DOWNMIX_3to0 = 0x0008,
|
||||
// DVD_KARAOKE_DOWNMIX_4to0 = 0x0010,
|
||||
// DVD_KARAOKE_DOWNMIX_Lto0 = 0x0020,
|
||||
// DVD_KARAOKE_DOWNMIX_Rto0 = 0x0040,
|
||||
// DVD_KARAOKE_DOWNMIX_0to1 = 0x0100,
|
||||
// DVD_KARAOKE_DOWNMIX_1to1 = 0x0200,
|
||||
// DVD_KARAOKE_DOWNMIX_2to1 = 0x0400,
|
||||
// DVD_KARAOKE_DOWNMIX_3to1 = 0x0800,
|
||||
// DVD_KARAOKE_DOWNMIX_4to1 = 0x1000,
|
||||
// DVD_KARAOKE_DOWNMIX_Lto1 = 0x2000,
|
||||
// DVD_KARAOKE_DOWNMIX_Rto1 = 0x4000
|
||||
// } DVDKaraokeDownmix_t;
|
||||
// typedef int DVDKaraokeDownmixMask_t;
|
||||
|
||||
// /* Display mode */
|
||||
// typedef enum {
|
||||
// DVD_DISPLAY_MODE_ContentDefault = 0,
|
||||
// DVD_DISPLAY_MODE_16x9 = 1,
|
||||
// DVD_DISPLAY_MODE_4x3PanScan = 2,
|
||||
// DVD_DISPLAY_MODE_4x3Letterboxed = 3
|
||||
// } DVDDisplayMode_t;
|
||||
|
||||
// /* Audio attributes */
|
||||
// typedef struct {
|
||||
// DVDAudioAppMode_t AppMode;
|
||||
// DVDAudioFormat_t AudioFormat;
|
||||
// DVDLangID_t Language;
|
||||
// DVDAudioLangExt_t LanguageExtension;
|
||||
// DVDBool_t HasMultichannelInfo;
|
||||
// DVDAudioSampleFreq_t SampleFrequency;
|
||||
// DVDAudioSampleQuant_t SampleQuantization;
|
||||
// DVDChannelNumber_t NumberOfChannels;
|
||||
// } DVDAudioAttributes_t;
|
||||
// typedef int DVDAudioSampleFreq_t;
|
||||
// typedef int DVDAudioSampleQuant_t;
|
||||
// typedef int DVDChannelNumber_t;
|
||||
|
||||
// /* Subpicture attributes */
|
||||
// typedef enum {
|
||||
// DVD_SUBPICTURE_TYPE_NotSpecified = 0,
|
||||
// DVD_SUBPICTURE_TYPE_Language = 1,
|
||||
// DVD_SUBPICTURE_TYPE_Other = 2
|
||||
// } DVDSubpictureType_t;
|
||||
// typedef enum {
|
||||
// DVD_SUBPICTURE_CODING_RunLength = 0,
|
||||
// DVD_SUBPICTURE_CODING_Extended = 1,
|
||||
// DVD_SUBPICTURE_CODING_Other = 2
|
||||
// } DVDSubpictureCoding_t;
|
||||
// typedef struct {
|
||||
// DVDSubpictureType_t Type;
|
||||
// DVDSubpictureCoding_t CodingMode;
|
||||
// DVDLangID_t Language;
|
||||
// DVDSubpictureLangExt_t LanguageExtension;
|
||||
// } DVDSubpictureAttributes_t;
|
||||
|
||||
// /* Video attributes */
|
||||
// typedef struct {
|
||||
// DVDBool_t PanscanPermitted;
|
||||
// DVDBool_t LetterboxPermitted;
|
||||
// int AspectX;
|
||||
// int AspectY;
|
||||
// int FrameRate;
|
||||
// int FrameHeight;
|
||||
// DVDVideoCompression_t Compression;
|
||||
// DVDBool_t Line21Field1InGop;
|
||||
// DVDBool_t Line21Field2InGop;
|
||||
// int more_to_come;
|
||||
// } DVDVideoAttributes_t;
|
||||
// typedef int DVDVideoCompression_t;
|
||||
|
||||
// #endif
|
10
dvdcss.h
Normal file
10
dvdcss.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
typedef struct dvdcss_s * dvdcss_t;
|
||||
typedef struct dvdcss_stream_cb dvdcss_stream_cb;
|
||||
dvdcss_t dvdcss_open (const char *psz_target);
|
||||
dvdcss_t dvdcss_open_stream (void *p_stream, dvdcss_stream_cb *p_stream_cb);
|
||||
int dvdcss_close (dvdcss_t);
|
||||
int dvdcss_seek (dvdcss_t, int i_blocks, int i_flags);
|
||||
int dvdcss_read (dvdcss_t, void *p_buffer, int i_blocks, int i_flags);
|
||||
int dvdcss_readv(dvdcss_t, void *p_iovec, int i_blocks, int i_flags);
|
||||
const char* dvdcss_error (const dvdcss_t);
|
||||
int dvdcss_is_scrambled (dvdcss_t);
|
718
dvdnav.h
Normal file
718
dvdnav.h
Normal file
|
@ -0,0 +1,718 @@
|
|||
/*
|
||||
* Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net>
|
||||
*
|
||||
* This file is part of libdvdnav, a DVD navigation library.
|
||||
*
|
||||
* libdvdnav 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.
|
||||
*
|
||||
* libdvdnav 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 libdvdnav; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the main header file applications should include if they want
|
||||
* to access dvdnav functionality.
|
||||
*/
|
||||
|
||||
// #include <dvdnav/dvd_types.h>
|
||||
// #include <dvdread/dvd_reader.h>
|
||||
// #include <dvdread/nav_types.h>
|
||||
// #include <dvdread/ifo_types.h> /* For vm_cmd_t */
|
||||
// #include <dvdnav/dvdnav_events.h>
|
||||
|
||||
// #include <stdarg.h>
|
||||
|
||||
/*********************************************************************
|
||||
* dvdnav data types *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* Opaque data-type can be viewed as a 'DVD handle'. You should get
|
||||
* a pointer to a dvdnav_t from the dvdnav_open() function.
|
||||
* Never call free() on the pointer, you have to give it back with
|
||||
* dvdnav_close().
|
||||
*/
|
||||
typedef struct dvdnav_s dvdnav_t;
|
||||
|
||||
/* Status as reported by most of libdvdnav's functions */
|
||||
typedef int32_t dvdnav_status_t;
|
||||
|
||||
typedef dvd_reader_stream_cb dvdnav_stream_cb;
|
||||
|
||||
/*
|
||||
* Unless otherwise stated, all functions return DVDNAV_STATUS_OK if
|
||||
* they succeeded, otherwise DVDNAV_STATUS_ERR is returned and the error may
|
||||
* be obtained by calling dvdnav_err_to_string().
|
||||
*/
|
||||
#define DVDNAV_STATUS_ERR 0
|
||||
#define DVDNAV_STATUS_OK 1
|
||||
|
||||
/*********************************************************************
|
||||
* initialisation & housekeeping functions *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* Logger callback definition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
DVDNAV_LOGGER_LEVEL_INFO,
|
||||
DVDNAV_LOGGER_LEVEL_ERROR,
|
||||
DVDNAV_LOGGER_LEVEL_WARN,
|
||||
DVDNAV_LOGGER_LEVEL_DEBUG,
|
||||
} dvdnav_logger_level_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *pf_log;
|
||||
} dvdnav_logger_cb;
|
||||
|
||||
/*
|
||||
* These functions allow you to open a DVD device and associate it
|
||||
* with a dvdnav_t.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Attempts to open the DVD drive at the specified path or using external
|
||||
* seek/read functions (dvdnav_open_stream) and pre-cache the CSS-keys.
|
||||
* libdvdread is used to access the DVD, so any source supported by libdvdread
|
||||
* can be given with "path" or "stream_cb". Currently, using dvdnav_open,
|
||||
* libdvdread can access : DVD drives, DVD image files, DVD file-by-file
|
||||
* copies. Using dvdnav_open_stream, libdvdread can access any kind of DVD
|
||||
* storage via custom implementation of seek/read functions.
|
||||
*
|
||||
* The resulting dvdnav_t handle will be written to *dest.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path);
|
||||
dvdnav_status_t
|
||||
dvdnav_open_stream(dvdnav_t **dest, void *priv, dvdnav_stream_cb *stream_cb);
|
||||
|
||||
dvdnav_status_t dvdnav_open2(dvdnav_t **dest,
|
||||
void *, const dvdnav_logger_cb *,
|
||||
const char *path);
|
||||
dvdnav_status_t dvdnav_open_stream2(dvdnav_t **dest,
|
||||
void *priv, const dvdnav_logger_cb *,
|
||||
dvdnav_stream_cb *stream_cb);
|
||||
|
||||
dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src);
|
||||
dvdnav_status_t dvdnav_free_dup(dvdnav_t * _this);
|
||||
|
||||
/*
|
||||
* Closes a dvdnav_t previously opened with dvdnav_open(), freeing any
|
||||
* memory associated with it.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_close(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Resets the DVD virtual machine and cache buffers.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_reset(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Fills a pointer with a value pointing to a string describing
|
||||
* the path associated with an open dvdnav_t. It assigns *path to NULL
|
||||
* on error.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_path(dvdnav_t *self, const char **path);
|
||||
|
||||
/*
|
||||
* Returns a human-readable string describing the last error.
|
||||
*/
|
||||
const char* dvdnav_err_to_string(dvdnav_t *self);
|
||||
|
||||
const char* dvdnav_version(void);
|
||||
|
||||
/*********************************************************************
|
||||
* changing and reading DVD player characteristics *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* These functions allow you to manipulate the various global characteristics
|
||||
* of the DVD playback engine.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sets the region mask (bit 0 set implies region 1, bit 1 set implies
|
||||
* region 2, etc) of the virtual machine. Generally you will only need to set
|
||||
* this if you are playing RCE discs which query the virtual machine as to its
|
||||
* region setting.
|
||||
*
|
||||
* This has _nothing_ to do with the region setting of the DVD drive.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *self, int32_t region_mask);
|
||||
|
||||
/*
|
||||
* Returns the region mask (bit 0 set implies region 1, bit 1 set implies
|
||||
* region 2, etc) of the virtual machine.
|
||||
*
|
||||
* This has _nothing_ to do with the region setting of the DVD drive.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_region_mask(dvdnav_t *self, int32_t *region_mask);
|
||||
|
||||
/*
|
||||
* Specify whether read-ahead caching should be used. You may not want this if your
|
||||
* decoding engine does its own buffering.
|
||||
*
|
||||
* The default read-ahead cache does not use an additional thread for the reading
|
||||
* (see read_cache.c for a threaded cache, but note that this code is currently
|
||||
* unmaintained). It prebuffers on VOBU level by reading ahead several buffers
|
||||
* on every read request. The speed of this prebuffering has been optimized to
|
||||
* also work on slow DVD drives.
|
||||
*
|
||||
* If in addition you want to prevent memcpy's to improve performance, have a look
|
||||
* at dvdnav_get_next_cache_block().
|
||||
*/
|
||||
dvdnav_status_t dvdnav_set_readahead_flag(dvdnav_t *self, int32_t read_ahead_flag);
|
||||
|
||||
/*
|
||||
* Query whether read-ahead caching/buffering will be used.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *self, int32_t *read_ahead_flag);
|
||||
|
||||
/*
|
||||
* Specify whether the positioning works PGC or PG based.
|
||||
* Programs (PGs) on DVDs are similar to Chapters and a program chain (PGC)
|
||||
* usually covers a whole feature. This affects the behaviour of the
|
||||
* functions dvdnav_get_position() and dvdnav_sector_search(). See there.
|
||||
* Default is PG based positioning.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_set_PGC_positioning_flag(dvdnav_t *self, int32_t pgc_based_flag);
|
||||
|
||||
/*
|
||||
* Query whether positioning is PG or PGC based.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_PGC_positioning_flag(dvdnav_t *self, int32_t *pgc_based_flag);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* reading data *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* These functions are used to poll the playback engine and actually get data
|
||||
* off the DVD.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Attempts to get the next block off the DVD and copies it into the buffer 'buf'.
|
||||
* If there is any special actions that may need to be performed, the value
|
||||
* pointed to by 'event' gets set accordingly.
|
||||
*
|
||||
* If 'event' is DVDNAV_BLOCK_OK then 'buf' is filled with the next block
|
||||
* (note that means it has to be at /least/ 2048 bytes big). 'len' is
|
||||
* then set to 2048.
|
||||
*
|
||||
* Otherwise, buf is filled with an appropriate event structure and
|
||||
* len is set to the length of that structure.
|
||||
*
|
||||
* See the dvdnav_events.h header for information on the various events.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_next_block(dvdnav_t *self, uint8_t *buf,
|
||||
int32_t *event, int32_t *len);
|
||||
|
||||
/*
|
||||
* This basically does the same as dvdnav_get_next_block. The only difference is
|
||||
* that it avoids a memcopy, when the requested block was found in the cache.
|
||||
* In such a case (cache hit) this function will return a different pointer than
|
||||
* the one handed in, pointing directly into the relevant block in the cache.
|
||||
* Those pointers must _never_ be freed but instead returned to the library via
|
||||
* dvdnav_free_cache_block().
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *self, uint8_t **buf,
|
||||
int32_t *event, int32_t *len);
|
||||
|
||||
/*
|
||||
* All buffers which came from the internal cache (when dvdnav_get_next_cache_block()
|
||||
* returned a buffer different from the one handed in) have to be freed with this
|
||||
* function. Although handing in other buffers not from the cache doesn't cause any harm.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf);
|
||||
|
||||
/*
|
||||
* If we are currently in a still-frame this function skips it.
|
||||
*
|
||||
* See also the DVDNAV_STILL_FRAME event.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_still_skip(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* If we are currently in WAIT state, that is: the application is required to
|
||||
* wait for its fifos to become empty, calling this signals libdvdnav that this
|
||||
* is achieved and that it can continue.
|
||||
*
|
||||
* See also the DVDNAV_WAIT event.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_wait_skip(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Returns the still time from the currently playing cell.
|
||||
* The still time is given in seconds with 0xff meaning an indefinite still.
|
||||
*
|
||||
* This function can be used to detect still frames before they are reached.
|
||||
* Some players might need this to prepare for a frame to be shown for a
|
||||
* longer time than usual.
|
||||
*/
|
||||
uint32_t dvdnav_get_next_still_flag(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Stops playback. The next event obtained with one of the get_next_block
|
||||
* functions will be a DVDNAV_STOP event.
|
||||
*
|
||||
* It is not required to call this before dvdnav_close().
|
||||
*/
|
||||
dvdnav_status_t dvdnav_stop(dvdnav_t *self);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* title/part navigation *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* Returns the number of titles on the disk.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *self, int32_t *titles);
|
||||
|
||||
/*
|
||||
* Returns the number of parts within the given title.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *self, int32_t title, int32_t *parts);
|
||||
|
||||
/*
|
||||
* Returns the number of angles for the given title.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_number_of_angles(dvdnav_t *self, int32_t title, int32_t *angles);
|
||||
|
||||
/*
|
||||
* Plays the specified title of the DVD from its beginning (that is: part 1).
|
||||
*/
|
||||
dvdnav_status_t dvdnav_title_play(dvdnav_t *self, int32_t title);
|
||||
|
||||
/*
|
||||
* Plays the specified title, starting from the specified part.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32_t title, int32_t part);
|
||||
|
||||
/*
|
||||
* Plays the specified title, starting from the specified program
|
||||
*/
|
||||
dvdnav_status_t dvdnav_program_play(dvdnav_t *self, int32_t title, int32_t pgcn, int32_t pgn);
|
||||
|
||||
/*
|
||||
* Stores in *times an array (that the application *must* free) of
|
||||
* dvdtimes corresponding to the chapter times for the chosen title.
|
||||
* *duration will have the duration of the title
|
||||
* The number of entries in *times is the result of the function.
|
||||
* On error *times is NULL and the output is 0
|
||||
*/
|
||||
uint32_t dvdnav_describe_title_chapters(dvdnav_t *self, int32_t title, uint64_t **times, uint64_t *duration);
|
||||
|
||||
/*
|
||||
* Play the specified amount of parts of the specified title of
|
||||
* the DVD then STOP.
|
||||
*
|
||||
* Currently unimplemented!
|
||||
*/
|
||||
dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *self, int32_t title,
|
||||
int32_t part, int32_t parts_to_play);
|
||||
|
||||
/*
|
||||
* Play the specified title starting from the specified time.
|
||||
*
|
||||
* Currently unimplemented!
|
||||
*/
|
||||
dvdnav_status_t dvdnav_time_play(dvdnav_t *self, int32_t title,
|
||||
uint64_t time);
|
||||
|
||||
/*
|
||||
* Stop playing the current position and jump to the specified menu.
|
||||
*
|
||||
* See also DVDMenuID_t from libdvdread
|
||||
*/
|
||||
dvdnav_status_t dvdnav_menu_call(dvdnav_t *self, DVDMenuID_t menu);
|
||||
|
||||
/*
|
||||
* Return the title number and part currently being played.
|
||||
* A title of 0 indicates we are in a menu. In this case, part
|
||||
* is set to the current menu's ID.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_current_title_info(dvdnav_t *self, int32_t *title,
|
||||
int32_t *part);
|
||||
|
||||
/*
|
||||
* Return the title number, pgcn and pgn currently being played.
|
||||
* A title of 0 indicates, we are in a menu.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_current_title_program(dvdnav_t *self, int32_t *title,
|
||||
int32_t *pgcn, int32_t *pgn);
|
||||
|
||||
/*
|
||||
* Return the current position (in blocks) within the current
|
||||
* title and the length (in blocks) of said title.
|
||||
*
|
||||
* Current implementation is wrong and likely to behave unpredictably!
|
||||
* Use is discouraged!
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *self,
|
||||
uint32_t *pos,
|
||||
uint32_t *len);
|
||||
|
||||
/*
|
||||
* This function is only available for compatibility reasons.
|
||||
*
|
||||
* Stop playing the current position and start playback of the current title
|
||||
* from the specified part.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_part_search(dvdnav_t *self, int32_t part);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* program chain/program navigation *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* Stop playing the current position and start playback from the last
|
||||
* VOBU boundary before the given sector. The sector number is not
|
||||
* meant to be an absolute physical DVD sector, but a relative sector
|
||||
* in the current program. This function cannot leave the current
|
||||
* program and will fail if asked to do so.
|
||||
*
|
||||
* If program chain based positioning is enabled
|
||||
* (see dvdnav_set_PGC_positioning_flag()), this will seek to the relative
|
||||
* sector inside the current program chain.
|
||||
*
|
||||
* 'origin' can be one of SEEK_SET, SEEK_CUR, SEEK_END as defined in
|
||||
* fcntl.h.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_sector_search(dvdnav_t *self,
|
||||
int64_t offset, int32_t origin);
|
||||
|
||||
/*
|
||||
returns the current stream time in PTS ticks as reported by the IFO structures
|
||||
divide it by 90000 to get the current play time in seconds
|
||||
*/
|
||||
int64_t dvdnav_get_current_time(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Stop playing the current position and start playback of the title
|
||||
* from the specified timecode.
|
||||
*
|
||||
* Currently implemented using interpolation. That interpolation is slightly
|
||||
* inaccurate.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_time_search(dvdnav_t *self,
|
||||
uint64_t time);
|
||||
|
||||
/*
|
||||
* Stop playing current position and play the "GoUp"-program chain.
|
||||
* (which generally leads to the title menu or a higher-level menu).
|
||||
*/
|
||||
dvdnav_status_t dvdnav_go_up(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Stop playing the current position and start playback at the
|
||||
* previous program (if it exists).
|
||||
*/
|
||||
dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Stop playing the current position and start playback at the
|
||||
* first program.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Stop playing the current position and start playback at the
|
||||
* next program (if it exists).
|
||||
*/
|
||||
dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Return the current position (in blocks) within the current
|
||||
* program and the length (in blocks) of current program.
|
||||
*
|
||||
* If program chain based positioning is enabled
|
||||
* (see dvdnav_set_PGC_positioning_flag()), this will return the
|
||||
* relative position in and the length of the current program chain.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_position(dvdnav_t *self, uint32_t *pos,
|
||||
uint32_t *len);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* menu highlights *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* Most functions related to highlights take a NAV PCI packet as a parameter.
|
||||
* While you can get such a packet from libdvdnav, this will result in
|
||||
* errors for players with internal FIFOs because due to the FIFO length,
|
||||
* libdvdnav will be ahead in the stream compared to what the user is
|
||||
* seeing on screen. Therefore, player applications who have a NAV
|
||||
* packet available, which is better in sync with the actual playback,
|
||||
* should always pass this one to these functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get the currently highlighted button
|
||||
* number (1..36) or 0 if no button is highlighted.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *self, int32_t *button);
|
||||
|
||||
/*
|
||||
* Returns the Presentation Control Information (PCI) structure associated
|
||||
* with the current position.
|
||||
*
|
||||
* Read the general notes above.
|
||||
* See also libdvdreads nav_types.h for definition of pci_t.
|
||||
*/
|
||||
pci_t* dvdnav_get_current_nav_pci(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Returns the DSI (data search information) structure associated
|
||||
* with the current position.
|
||||
*
|
||||
* Read the general notes above.
|
||||
* See also libdvdreads nav_types.h for definition of dsi_t.
|
||||
*/
|
||||
dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Get the area associated with a certain button.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_highlight_area(pci_t *nav_pci , int32_t button, int32_t mode,
|
||||
dvdnav_highlight_area_t *highlight);
|
||||
|
||||
/*
|
||||
* Move button highlight around as suggested by function name (e.g. with arrow keys).
|
||||
*/
|
||||
dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *self, pci_t *pci);
|
||||
dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *self, pci_t *pci);
|
||||
dvdnav_status_t dvdnav_right_button_select(dvdnav_t *self, pci_t *pci);
|
||||
dvdnav_status_t dvdnav_left_button_select(dvdnav_t *self, pci_t *pci);
|
||||
|
||||
/*
|
||||
* Activate ("press") the currently highlighted button.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_button_activate(dvdnav_t *self, pci_t *pci);
|
||||
|
||||
/*
|
||||
* Highlight a specific button.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_button_select(dvdnav_t *self, pci_t *pci, int32_t button);
|
||||
|
||||
/*
|
||||
* Activate ("press") specified button.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_button_select_and_activate(dvdnav_t *self, pci_t *pci, int32_t button);
|
||||
|
||||
/*
|
||||
* Activate ("press") a button and execute specified command.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *self, int32_t button, vm_cmd_t *cmd);
|
||||
|
||||
/*
|
||||
* Select button at specified video frame coordinates.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_mouse_select(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y);
|
||||
|
||||
/*
|
||||
* Activate ("press") button at specified video frame coordinates.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_mouse_activate(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* languages *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* The language codes expected by these functions are two character
|
||||
* codes as defined in ISO639.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set which menu language we should use per default.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_menu_language_select(dvdnav_t *self,
|
||||
char *code);
|
||||
|
||||
/*
|
||||
* Set which audio language we should use per default.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_audio_language_select(dvdnav_t *self,
|
||||
char *code);
|
||||
|
||||
/*
|
||||
* Set which spu language we should use per default.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_spu_language_select(dvdnav_t *self,
|
||||
char *code);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* obtaining stream attributes *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* Return a string describing the title of the DVD.
|
||||
* This is an ID string encoded on the disc by the author. In many cases
|
||||
* this is a descriptive string such as `THE_MATRIX' but sometimes is singularly
|
||||
* uninformative such as `PDVD-011421'. Some DVD authors even forget to set this,
|
||||
* so you may also read the default of the authoring software they used, like
|
||||
* `DVDVolume'.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_title_string(dvdnav_t *self, const char **title_str);
|
||||
|
||||
/*
|
||||
* Returns a string containing the serial number of the DVD.
|
||||
* This has a max of 15 characters and should be more unique than the
|
||||
* title string.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_serial_string(dvdnav_t *self, const char **serial_str);
|
||||
|
||||
/*
|
||||
* Get video aspect code.
|
||||
* The aspect code does only change on VTS boundaries.
|
||||
* See the DVDNAV_VTS_CHANGE event.
|
||||
*
|
||||
* 0 -- 4:3, 2 -- 16:9
|
||||
*/
|
||||
uint8_t dvdnav_get_video_aspect(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Get video resolution.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_video_resolution(dvdnav_t *self, uint32_t *width, uint32_t *height);
|
||||
|
||||
/*
|
||||
* Get video scaling permissions.
|
||||
* The scaling permission does only change on VTS boundaries.
|
||||
* See the DVDNAV_VTS_CHANGE event.
|
||||
*
|
||||
* bit0 set = deny letterboxing, bit1 set = deny pan&scan
|
||||
*/
|
||||
uint8_t dvdnav_get_video_scale_permission(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Converts a *logical* audio stream id into language code
|
||||
* (returns 0xffff if no such stream).
|
||||
*/
|
||||
uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *self, uint8_t stream);
|
||||
|
||||
/*
|
||||
* Returns the format of *logical* audio stream 'stream'
|
||||
* (returns 0xffff if no such stream).
|
||||
*/
|
||||
uint16_t dvdnav_audio_stream_format(dvdnav_t *self, uint8_t stream);
|
||||
|
||||
/*
|
||||
* Returns number of channels in *logical* audio stream 'stream'
|
||||
* (returns 0xffff if no such stream).
|
||||
*/
|
||||
uint16_t dvdnav_audio_stream_channels(dvdnav_t *self, uint8_t stream);
|
||||
|
||||
/*
|
||||
* Converts a *logical* subpicture stream id into country code
|
||||
* (returns 0xffff if no such stream).
|
||||
*/
|
||||
uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *self, uint8_t stream);
|
||||
|
||||
/*
|
||||
* Converts a *physical* (MPEG) audio stream id into a logical stream number.
|
||||
*/
|
||||
int8_t dvdnav_get_audio_logical_stream(dvdnav_t *self, uint8_t audio_num);
|
||||
|
||||
/*
|
||||
* Get audio attr
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_audio_attr(dvdnav_t *self, uint8_t audio_mum, audio_attr_t *audio_attr);
|
||||
|
||||
/*
|
||||
* Converts a *physical* (MPEG) subpicture stream id into a logical stream number.
|
||||
*/
|
||||
int8_t dvdnav_get_spu_logical_stream(dvdnav_t *self, uint8_t subp_num);
|
||||
|
||||
/*
|
||||
* Get spu attr
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_spu_attr(dvdnav_t *self, uint8_t audio_mum, subp_attr_t *subp_attr);
|
||||
|
||||
/*
|
||||
* Get active audio stream.
|
||||
*/
|
||||
int8_t dvdnav_get_active_audio_stream(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Get active spu stream.
|
||||
*/
|
||||
int8_t dvdnav_get_active_spu_stream(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Get the set of user operations that are currently prohibited.
|
||||
* There are potentially new restrictions right after
|
||||
* DVDNAV_CHANNEL_HOP and DVDNAV_NAV_PACKET.
|
||||
*/
|
||||
user_ops_t dvdnav_get_restrictions(dvdnav_t *self);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* multiple angles *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* The libdvdnav library abstracts away the difference between seamless and
|
||||
* non-seamless angles. From the point of view of the programmer you just set the
|
||||
* angle number and all is well in the world. You will always see only the
|
||||
* selected angle coming from the get_next_block functions.
|
||||
*
|
||||
* Note:
|
||||
* It is quite possible that some tremendously strange DVD feature might change the
|
||||
* angle number from under you. Generally you should always view the results from
|
||||
* dvdnav_get_angle_info() as definitive only up to the next time you call
|
||||
* dvdnav_get_next_block().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sets the current angle. If you try to follow a non existent angle
|
||||
* the call fails.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_angle_change(dvdnav_t *self, int32_t angle);
|
||||
|
||||
/*
|
||||
* Returns the current angle and number of angles present.
|
||||
*/
|
||||
dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *self, int32_t *current_angle,
|
||||
int32_t *number_of_angles);
|
||||
|
||||
/*********************************************************************
|
||||
* domain queries *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* Are we in the First Play domain?
|
||||
*/
|
||||
int8_t dvdnav_is_domain_fp(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Are we in the Video management Menu domain?
|
||||
*/
|
||||
int8_t dvdnav_is_domain_vmgm(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Are we in the Video Title Menu domain?
|
||||
*/
|
||||
int8_t dvdnav_is_domain_vtsm(dvdnav_t *self);
|
||||
|
||||
/*
|
||||
* Are we in the Video Title Set domain?
|
||||
*/
|
||||
int8_t dvdnav_is_domain_vts(dvdnav_t *self);
|
212
dvdnav.py
Normal file
212
dvdnav.py
Normal file
|
@ -0,0 +1,212 @@
|
|||
import cffi
|
||||
import os
|
||||
import functools
|
||||
from datetime import timedelta
|
||||
from tqdm import tqdm
|
||||
|
||||
def loadlib(dll_path,*includes,**kwargs):
|
||||
ffi = cffi.FFI()
|
||||
for include in includes:
|
||||
ffi.cdef(open(include).read(),kwargs)
|
||||
return ffi,ffi.dlopen(dll_path)
|
||||
|
||||
class DVDError(Exception):
|
||||
pass
|
||||
|
||||
class DVDNav(object):
|
||||
def __init__(self,path,verbose=2,method="disc"):
|
||||
os.environ["DVDCSS_VERBOSE"]=str(verbose)
|
||||
os.environ["DVDCSS_METHOD"]=method
|
||||
self.dvd=None
|
||||
self.ffi,self.lib = loadlib("libdvdnav-4.dll",
|
||||
"dvd_types.h",
|
||||
"dvd_reader.h",
|
||||
"ifo_types.h",
|
||||
"nav_types.h",
|
||||
"dvdnav_events.h",
|
||||
"dvdnav.h")
|
||||
self.path=path
|
||||
self.titles={}
|
||||
self.open(path)
|
||||
|
||||
def __del__(self):
|
||||
self.__check_error(self.lib.dvdnav_close(self.dvd))
|
||||
self.dvd=None
|
||||
|
||||
def __repr__(self):
|
||||
return "<DVD Path={0.path} Title={0.title} Serial={0.serial}".format(self)
|
||||
|
||||
def get_blocks(self,title,angle=1,slang=None):
|
||||
self.__check_error(self.lib.dvdnav_set_PGC_positioning_flag(self.dvd,1))
|
||||
self.__check_error(self.lib.dvdnav_title_play(self.dvd,title))
|
||||
self.__check_error(self.lib.dvdnav_angle_change(self.dvd,angle))
|
||||
if slang is not None:
|
||||
self.__check_error(self.lib.dvdnav_spu_language_select(self.dvd,slang))
|
||||
event=self.lib.DVDNAV_NOP
|
||||
buf=self.ffi.new("char[]",4096)
|
||||
ev=self.ffi.new("int32_t*",self.lib.DVDNAV_NOP)
|
||||
size=self.ffi.new("int32_t*",0)
|
||||
pos=self.ffi.new("uint32_t*",0)
|
||||
total_size=self.ffi.new("uint32_t*",0)
|
||||
domains = {
|
||||
1: "FirstPlay",
|
||||
2: "VTSTitle",
|
||||
4: "VMGM",
|
||||
8: "VTSMenu"
|
||||
}
|
||||
events={
|
||||
0: "DVDNAV_BLOCK_OK",
|
||||
1: "DVDNAV_NOP",
|
||||
2: "DVDNAV_STILL_FRAME",
|
||||
3: "DVDNAV_SPU_STREAM_CHANGE",
|
||||
4: "DVDNAV_AUDIO_STREAM_CHANGE",
|
||||
5: "DVDNAV_VTS_CHANGE",
|
||||
6: "DVDNAV_CELL_CHANGE",
|
||||
7: "DVDNAV_NAV_PACKET",
|
||||
8: "DVDNAV_STOP",
|
||||
9: "DVDNAV_HIGHLIGHT",
|
||||
10: "DVDNAV_SPU_CLUT_CHANGE",
|
||||
12: "DVDNAV_HOP_CHANNEL",
|
||||
13: "DVDNAV_WAIT"
|
||||
}
|
||||
progbar=tqdm(unit_divisor=1024,unit_scale=True,unit="iB",desc="Ripping DVD")
|
||||
while True:
|
||||
self.__check_error(self.lib.dvdnav_get_next_block(self.dvd,buf,ev,size))
|
||||
if self.lib.dvdnav_get_position(self.dvd,pos,total_size)==self.lib.DVDNAV_STATUS_OK:
|
||||
progbar.total=total_size[0]*2048
|
||||
progbar.n=max(progbar.n,min(progbar.total,pos[0]*2048))
|
||||
progbar.update(0)
|
||||
# print("Got event:",events.get(ev[0],ev[0]),size[0])
|
||||
if ev[0] in [self.lib.DVDNAV_SPU_CLUT_CHANGE,self.lib.DVDNAV_HOP_CHANNEL,self.lib.DVDNAV_NOP]:
|
||||
continue
|
||||
elif ev[0]==self.lib.DVDNAV_BLOCK_OK:
|
||||
# print("Read",size[0])
|
||||
yield self.ffi.buffer(buf,size[0])[:]
|
||||
elif ev[0]==self.lib.DVDNAV_STOP:
|
||||
break
|
||||
elif ev[0]==self.lib.DVDNAV_NAV_PACKET:
|
||||
nav=self.lib.dvdnav_get_current_nav_pci(self.dvd)
|
||||
# print("PTS:",timedelta(seconds=nav.pci_gi.vobu_s_ptm/90000))
|
||||
elif ev[0]==self.lib.DVDNAV_STILL_FRAME:
|
||||
# print("Still")
|
||||
self.__check_error(self.lib.dvdnav_still_skip(self.dvd))
|
||||
elif ev[0]==self.lib.DVDNAV_WAIT:
|
||||
# print("Wait",size[0])
|
||||
self.__check_error(self.lib.dvdnav_wait_skip(self.dvd))
|
||||
elif ev[0]==self.lib.DVDNAV_SPU_STREAM_CHANGE:
|
||||
spu=self.ffi.cast("dvdnav_spu_stream_change_event_t*",buf)
|
||||
progbar.write(f"[{title}|{angle}] SPU: Wide: {spu.physical_wide} Letterbox: {spu.physical_letterbox} Pan&Scan: {spu.physical_pan_scan} Logical: {spu.logical}")
|
||||
elif ev[0]==self.lib.DVDNAV_AUDIO_STREAM_CHANGE:
|
||||
audio=self.ffi.cast("dvdnav_audio_stream_change_event_t*",buf)
|
||||
progbar.write(f"[{title}|{angle}] Audio: Physical: {audio.physical} Logical: {audio.logical}")
|
||||
elif ev[0]==self.lib.DVDNAV_CELL_CHANGE:
|
||||
cell=self.ffi.cast("dvdnav_cell_change_event_t*",buf)
|
||||
progbar.write(f"[{title}|{angle}] Cell: {cell.cellN} ({cell.cell_start}-{cell.cell_start+cell.cell_length}), PG: {cell.pgN} ({cell.pg_start}-{cell.pg_start+cell.pg_length})")
|
||||
elif ev[0]==self.lib.DVDNAV_VTS_CHANGE:
|
||||
vts=self.ffi.cast("dvdnav_vts_change_event_t*",buf)
|
||||
old_domain=sorted(domains[k] for k in domains if vts.old_domain&k)
|
||||
new_domain=sorted(domains[k] for k in domains if vts.new_domain&k)
|
||||
progbar.write(f"[{title}|{angle}] VTS: {vts.old_vtsN} ({vts.old_domain} {old_domain}) -> {vts.new_vtsN} ({vts.new_domain} {new_domain})")
|
||||
if vts.new_domain==8: # back to menu
|
||||
break
|
||||
else:
|
||||
progbar.write(f"[{title}|{angle}] Unhandled: {events.get(ev[0],ev[0])} {size[0]}")
|
||||
|
||||
|
||||
def __check_error(self,ret):
|
||||
if ret==self.lib.DVDNAV_STATUS_ERR:
|
||||
if self.dvd:
|
||||
err=self.ffi.string(self.lib.dvdnav_err_to_string(self.dvd))
|
||||
raise DVDError(err)
|
||||
raise DVDError("Unknown error")
|
||||
|
||||
def __get_titles(self):
|
||||
titles=self.ffi.new("int32_t*",0)
|
||||
p_times=self.ffi.new("uint64_t[]",512)
|
||||
times=self.ffi.new("uint64_t**",p_times)
|
||||
duration=self.ffi.new("uint64_t*",0)
|
||||
titles=self.ffi.new("int32_t*",0)
|
||||
self.lib.dvdnav_get_number_of_titles(self.dvd,titles)
|
||||
num_titles=titles[0]
|
||||
for title in range(0,num_titles+1):
|
||||
if self.lib.dvdnav_get_number_of_parts(self.dvd,title,titles)==0:
|
||||
continue
|
||||
num_parts=titles[0]
|
||||
self.lib.dvdnav_get_number_of_angles(self.dvd,title,titles)
|
||||
num_angles=titles[0]
|
||||
num_chapters=self.lib.dvdnav_describe_title_chapters(self.dvd,title,times,duration)
|
||||
if duration[0]==0:
|
||||
continue
|
||||
chapters=[]
|
||||
for t in range(num_chapters):
|
||||
chapters.append(timedelta(seconds=times[0][t]/90000))
|
||||
self.titles[title]={
|
||||
'parts':num_parts,
|
||||
'angles': num_angles,
|
||||
'duration': timedelta(seconds=duration[0]/90000),
|
||||
'chapters': chapters
|
||||
}
|
||||
|
||||
def __get_info(self):
|
||||
s=self.ffi.new("char**",self.ffi.NULL)
|
||||
self.lib.dvdnav_get_title_string(self.dvd,s)
|
||||
self.title=str(self.ffi.string(s[0]),"utf8").strip() or None
|
||||
self.lib.dvdnav_get_serial_string(self.dvd,s)
|
||||
self.serial=str(self.ffi.string(s[0]),"utf8").strip() or None
|
||||
self.__get_titles()
|
||||
|
||||
def open(self,path):
|
||||
audio_attrs=self.ffi.new("audio_attr_t*")
|
||||
spu_attr=self.ffi.new("subp_attr_t*")
|
||||
dvdnav=self.ffi.new("dvdnav_t**",self.ffi.cast("dvdnav_t*",0))
|
||||
self.__check_error(self.lib.dvdnav_open(dvdnav,bytes(path,"utf8")))
|
||||
self.dvd=dvdnav[0]
|
||||
self.__check_error(self.lib.dvdnav_set_readahead_flag(self.dvd,1))
|
||||
self.__get_info()
|
||||
for title in self.titles:
|
||||
self.__check_error(self.lib.dvdnav_title_play(self.dvd,title))
|
||||
self.titles[title]['audio']={}
|
||||
self.titles[title]['subtitles']={}
|
||||
for n in range(255):
|
||||
stream_id=self.lib.dvdnav_get_audio_logical_stream(self.dvd,n)
|
||||
if stream_id==-1:
|
||||
continue
|
||||
self.__check_error(self.lib.dvdnav_get_audio_attr(self.dvd,stream_id,audio_attrs))
|
||||
alang=None
|
||||
if audio_attrs.lang_type:
|
||||
alang = str(audio_attrs.lang_code.to_bytes(2,'big'),"utf8")
|
||||
channels = audio_attrs.channels+1
|
||||
codec = {
|
||||
0: 'ac3',
|
||||
2: 'mpeg1',
|
||||
3: 'mpeg-2ext',
|
||||
4: 'lpcm',
|
||||
6: 'dts'
|
||||
}[audio_attrs.audio_format]
|
||||
audio_type={
|
||||
0: None,
|
||||
1: 'normal',
|
||||
2: 'descriptive',
|
||||
3: "director's commentary",
|
||||
4: "alternate director's commentary"
|
||||
}[audio_attrs.code_extension]
|
||||
self.titles[title]['audio'][n]={
|
||||
'stream_id': stream_id,
|
||||
'lang':alang,
|
||||
'channels': channels,
|
||||
'codec': codec,
|
||||
'type': audio_type
|
||||
}
|
||||
for n in range(255):
|
||||
stream_id=self.lib.dvdnav_get_spu_logical_stream(self.dvd,n)
|
||||
if stream_id==-1:
|
||||
continue
|
||||
self.__check_error(self.lib.dvdnav_get_spu_attr(self.dvd,stream_id,spu_attr))
|
||||
slang = None
|
||||
if spu_attr.type==1:
|
||||
slang = str(spu_attr.lang_code.to_bytes(2,'big'),"utf8")
|
||||
self.titles[title]['subtitles'][n]={
|
||||
'stream_id': stream_id,
|
||||
'lang':slang
|
||||
}
|
||||
self.__check_error(self.lib.dvdnav_stop(self.dvd))
|
230
dvdnav_events.h
Normal file
230
dvdnav_events.h
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net>
|
||||
*
|
||||
* This file is part of libdvdnav, a DVD navigation library.
|
||||
*
|
||||
* libdvdnav 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.
|
||||
*
|
||||
* libdvdnav 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 libdvdnav; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header defines events and event types
|
||||
*/
|
||||
|
||||
/*
|
||||
* DVDNAV_BLOCK_OK
|
||||
*
|
||||
* A regular data block from the DVD has been returned.
|
||||
* This one should be demuxed and decoded for playback.
|
||||
*/
|
||||
#define DVDNAV_BLOCK_OK 0
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_NOP
|
||||
*
|
||||
* Just ignore this.
|
||||
*/
|
||||
#define DVDNAV_NOP 1
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_STILL_FRAME
|
||||
*
|
||||
* We have reached a still frame. The player application should wait
|
||||
* the amount of time specified by the still's length while still handling
|
||||
* user input to make menus and other interactive stills work.
|
||||
* The last delivered frame should be kept showing.
|
||||
* Once the still has timed out, call dvdnav_skip_still().
|
||||
* A length of 0xff means an infinite still which has to be skipped
|
||||
* indirectly by some user interaction.
|
||||
*/
|
||||
#define DVDNAV_STILL_FRAME 2
|
||||
|
||||
typedef struct {
|
||||
/* The length (in seconds) the still frame should be displayed for,
|
||||
* or 0xff if infinite. */
|
||||
int length;
|
||||
} dvdnav_still_event_t;
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_SPU_STREAM_CHANGE
|
||||
*
|
||||
* Inform the SPU decoding/overlaying engine to switch SPU channels.
|
||||
*/
|
||||
#define DVDNAV_SPU_STREAM_CHANGE 3
|
||||
|
||||
typedef struct {
|
||||
/* The physical (MPEG) stream number for widescreen SPU display.
|
||||
* Use this, if you blend the SPU on an anamorphic image before
|
||||
* unsqueezing it. */
|
||||
int physical_wide;
|
||||
|
||||
/* The physical (MPEG) stream number for letterboxed display.
|
||||
* Use this, if you blend the SPU on an anamorphic image after
|
||||
* unsqueezing it. */
|
||||
int physical_letterbox;
|
||||
|
||||
/* The physical (MPEG) stream number for pan&scan display.
|
||||
* Use this, if you blend the SPU on an anamorphic image after
|
||||
* unsqueezing it the pan&scan way. */
|
||||
int physical_pan_scan;
|
||||
|
||||
/* The logical (DVD) stream number. */
|
||||
int logical;
|
||||
} dvdnav_spu_stream_change_event_t;
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_AUDIO_STREAM_CHANGE
|
||||
*
|
||||
* Inform the audio decoder to switch channels.
|
||||
*/
|
||||
#define DVDNAV_AUDIO_STREAM_CHANGE 4
|
||||
|
||||
typedef struct {
|
||||
/* The physical (MPEG) stream number. */
|
||||
int physical;
|
||||
|
||||
/* The logical (DVD) stream number. */
|
||||
int logical;
|
||||
} dvdnav_audio_stream_change_event_t;
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_VTS_CHANGE
|
||||
*
|
||||
* Some status information like video aspect and video scale permissions do
|
||||
* not change inside a VTS. Therefore this event can be used to query such
|
||||
* information only when necessary and update the decoding/displaying
|
||||
* accordingly.
|
||||
*/
|
||||
#define DVDNAV_VTS_CHANGE 5
|
||||
|
||||
typedef struct {
|
||||
int old_vtsN; /* the old VTS number */
|
||||
DVDDomain_t old_domain; /* the old domain */
|
||||
int new_vtsN; /* the new VTS number */
|
||||
DVDDomain_t new_domain; /* the new domain */
|
||||
} dvdnav_vts_change_event_t;
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_CELL_CHANGE
|
||||
*
|
||||
* Some status information like the current Title and Part numbers do not
|
||||
* change inside a cell. Therefore this event can be used to query such
|
||||
* information only when necessary and update the decoding/displaying
|
||||
* accordingly.
|
||||
* Some useful information for accurate time display is also reported
|
||||
* together with this event.
|
||||
*/
|
||||
#define DVDNAV_CELL_CHANGE 6
|
||||
|
||||
typedef struct {
|
||||
int cellN; /* the new cell number */
|
||||
int pgN; /* the current program number */
|
||||
int64_t cell_length; /* the length of the current cell in sectors */
|
||||
int64_t pg_length; /* the length of the current program in sectors */
|
||||
int64_t pgc_length; /* the length of the current program chain in PTS ticks */
|
||||
int64_t cell_start; /* the start offset of the current cell relatively to the PGC in sectors */
|
||||
int64_t pg_start; /* the start offset of the current PG relatively to the PGC in sectors */
|
||||
} dvdnav_cell_change_event_t;
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_NAV_PACKET
|
||||
*
|
||||
* NAV packets are useful for various purposes. They define the button
|
||||
* highlight areas and VM commands of DVD menus, so they should in any
|
||||
* case be sent to the SPU decoder/overlaying engine for the menus to work.
|
||||
* NAV packets also provide a way to detect PTS discontinuities, because
|
||||
* they carry the start and end PTS values for the current VOBU.
|
||||
* (pci.vobu_s_ptm and pci.vobu_e_ptm) Whenever the start PTS of the
|
||||
* current NAV does not match the end PTS of the previous NAV, a PTS
|
||||
* discontinuity has occured.
|
||||
* NAV packets can also be used for time display, because they are
|
||||
* timestamped relatively to the current Cell.
|
||||
*/
|
||||
#define DVDNAV_NAV_PACKET 7
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_STOP
|
||||
*
|
||||
* Applications should end playback here. A subsequent dvdnav_get_next_block()
|
||||
* call will restart the VM from the beginning of the DVD.
|
||||
*/
|
||||
#define DVDNAV_STOP 8
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_HIGHLIGHT
|
||||
*
|
||||
* The current button highlight changed. Inform the overlaying engine to
|
||||
* highlight a different button. Please note, that at the moment only mode 1
|
||||
* highlights are reported this way. That means, when the button highlight
|
||||
* has been moved around by some function call, you will receive an event
|
||||
* telling you the new button. But when a button gets activated, you have
|
||||
* to handle the mode 2 highlighting (that is some different colour the
|
||||
* button turns to on activation) in your application.
|
||||
*/
|
||||
#define DVDNAV_HIGHLIGHT 9
|
||||
|
||||
typedef struct {
|
||||
/* highlight mode: 0 - hide, 1 - show, 2 - activate, currently always 1 */
|
||||
int display;
|
||||
|
||||
/* FIXME: these fields are currently not set */
|
||||
uint32_t palette; /* The CLUT entries for the highlight palette
|
||||
(4-bits per entry -> 4 entries) */
|
||||
uint16_t sx,sy,ex,ey; /* The start/end x,y positions */
|
||||
uint32_t pts; /* Highlight PTS to match with SPU */
|
||||
|
||||
/* button number for the SPU decoder/overlaying engine */
|
||||
uint32_t buttonN;
|
||||
} dvdnav_highlight_event_t;
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_SPU_CLUT_CHANGE
|
||||
*
|
||||
* Inform the SPU decoder/overlaying engine to update its colour lookup table.
|
||||
* The CLUT is given as 16 uint32_t's in the buffer.
|
||||
*/
|
||||
#define DVDNAV_SPU_CLUT_CHANGE 10
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_HOP_CHANNEL
|
||||
*
|
||||
* A non-seamless operation has been performed. Applications can drop all
|
||||
* their internal fifo's content, which will speed up the response.
|
||||
*/
|
||||
#define DVDNAV_HOP_CHANNEL 12
|
||||
|
||||
|
||||
/*
|
||||
* DVDNAV_WAIT
|
||||
*
|
||||
* We have reached a point in DVD playback, where timing is critical.
|
||||
* Player application with internal fifos can introduce state
|
||||
* inconsistencies, because libdvdnav is always the fifo's length
|
||||
* ahead in the stream compared to what the application sees.
|
||||
* Such applications should wait until their fifos are empty
|
||||
* when they receive this type of event.
|
||||
* Once this is achieved, call dvdnav_skip_wait().
|
||||
*/
|
||||
#define DVDNAV_WAIT 13
|
43
dvdread.py
Normal file
43
dvdread.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
import cffi
|
||||
import os
|
||||
import functools
|
||||
import binascii
|
||||
from datetime import timedelta
|
||||
|
||||
def loadlib(dll_path,*includes,**kwargs):
|
||||
ffi = cffi.FFI()
|
||||
for include in includes:
|
||||
ffi.cdef(open(include).read(),**kwargs)
|
||||
return ffi,ffi.dlopen(dll_path)
|
||||
|
||||
class DVDRead(object):
|
||||
def __init__(self,path):
|
||||
self.dvd=None
|
||||
self.ffi,self.lib = loadlib("libdvdread-8.dll",
|
||||
"dvd_types.h",
|
||||
"dvd_reader.h",
|
||||
"ifo_types.h",
|
||||
"ifo_read.h",
|
||||
"ifo_print.h",
|
||||
"nav_types.h",
|
||||
"nav_read.h",
|
||||
"nav_print.h")
|
||||
self.path=path
|
||||
self.titles={}
|
||||
self.open(path)
|
||||
|
||||
def __del__(self):
|
||||
if self.dvd:
|
||||
self.lib.DVDClose(self.dvd)
|
||||
|
||||
def open(self,path):
|
||||
# self.dvd_css=self.css_lib.dvdcss_open()
|
||||
self.dvd=self.lib.DVDOpen(bytes(path,"utf8"))
|
||||
vol_id=self.ffi.new("unsigned char[]",32)
|
||||
self.lib.DVDDiscID(self.dvd,vol_id)
|
||||
self.disc_id=str(binascii.hexlify(self.ffi.buffer(vol_id,16)[:]),"utf8")
|
||||
self.lib.DVDUDFVolumeInfo(self.dvd,vol_id,32,self.ffi.NULL,0)
|
||||
self.udf_disc_name=str(self.ffi.string(vol_id),"utf8")
|
||||
self.lib.DVDISOVolumeInfo(self.dvd,vol_id,32,self.ffi.NULL,0)
|
||||
self.iso_disc_name=str(self.ffi.string(vol_id),"utf8")
|
||||
self.ffi.release(vol_id)
|
173
ff_d2v.py
Normal file
173
ff_d2v.py
Normal file
|
@ -0,0 +1,173 @@
|
|||
import sys
|
||||
import json
|
||||
import os
|
||||
import subprocess as SP
|
||||
import itertools as ITT
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
colorspace={
|
||||
"gbr": 0,
|
||||
"bt709": 1,
|
||||
"unknown": 2,
|
||||
"fcc": 4,
|
||||
"bt470bg": 5,
|
||||
"smpte170m": 6,
|
||||
"smpte240m": 7,
|
||||
"ycgco": 8,
|
||||
"bt2020nc": 9,
|
||||
"bt2020c": 10,
|
||||
"smpte2085": 11,
|
||||
"chroma-derived-nc": 12,
|
||||
"chroma-derived-c": 13,
|
||||
"ictcp": 14,
|
||||
}
|
||||
|
||||
pict_types={
|
||||
'I':0b01,
|
||||
'P':0b10,
|
||||
'B':0b11
|
||||
}
|
||||
|
||||
def make_info(frames):
|
||||
has_interlaced = any(frame['interlaced_frame'] for frame in frames)
|
||||
new_gop='timecode' in frames[0].get('tags',{})
|
||||
info=0x000
|
||||
info|=1<<11 # always 1
|
||||
info|=0<<10 # 0=Closed GOP, 1=Open GOP
|
||||
info|=(not has_interlaced)<<9 # Progressive
|
||||
info|=new_gop<<8
|
||||
return info
|
||||
|
||||
def make_flags(frames):
|
||||
flags=[]
|
||||
for frame in frames:
|
||||
needs_prev=False
|
||||
progressive=not int(frame['interlaced_frame'])
|
||||
pt=pict_types[frame['pict_type']]
|
||||
reserved=0b00
|
||||
tff=int(frame['top_field_first'])
|
||||
rff=int(frame['repeat_pict'])
|
||||
flag=0b0
|
||||
flag|=(not needs_prev)<<7
|
||||
flag|=progressive<<6
|
||||
flag|=pt<<4
|
||||
flag|=reserved<<2
|
||||
flag|=tff<<1
|
||||
flag|=rff
|
||||
flags.append(f"{flag:02x}")
|
||||
return flags
|
||||
|
||||
|
||||
def make_line(frames,stream):
|
||||
info=f"{make_info(frames):03x}"
|
||||
matrix=colorspace[stream['color_space']]
|
||||
file=0
|
||||
position=frames[0]['pkt_pos']
|
||||
skip=0
|
||||
vob=0
|
||||
cell=0
|
||||
flags=make_flags(frames)
|
||||
return " ".join(map(str,[info,matrix,file,position,skip,vob,cell,*flags]))
|
||||
|
||||
|
||||
def get_frames(path):
|
||||
proc=SP.Popen([
|
||||
"ffprobe",
|
||||
"-probesize", str(0x7fffffff),
|
||||
"-analyzeduration", str(0x7fffffff),
|
||||
"-v","fatal",
|
||||
"-i",path,
|
||||
"-select_streams","v:0",
|
||||
"-show_frames",
|
||||
"-print_format","compact"
|
||||
],stdout=SP.PIPE,stdin=SP.DEVNULL,bufsize=0)
|
||||
data=None
|
||||
for line in proc.stdout:
|
||||
line=str(line,"utf8").strip().split("|")
|
||||
line={line[0]: dict(v.split("=") for v in line[1:])}
|
||||
yield line
|
||||
ret=proc.wait()
|
||||
if ret!=0:
|
||||
exit(ret)
|
||||
return data
|
||||
|
||||
def get_streams(path):
|
||||
proc=SP.Popen([
|
||||
"ffprobe",
|
||||
"-probesize", str(0x7fffffff),
|
||||
"-analyzeduration", str(0x7fffffff),
|
||||
"-v","fatal",
|
||||
"-i",path,
|
||||
"-select_streams","v:0",
|
||||
"-show_streams",
|
||||
"-show_format",
|
||||
"-print_format","json"
|
||||
],stdout=SP.PIPE,stdin=SP.DEVNULL,bufsize=0)
|
||||
data=json.load(proc.stdout)
|
||||
ret=proc.wait()
|
||||
if ret!=0:
|
||||
exit(ret)
|
||||
return data['streams'],data['format']
|
||||
|
||||
def make_header(file):
|
||||
return ["DGIndexProjectFile16","1",os.path.abspath(file)]
|
||||
|
||||
def make_settings(stream):
|
||||
pict_size="x".join(map(str,[stream["width"],stream["height"]]))
|
||||
frame_rate = list(map(int,stream['r_frame_rate'].split("/")))
|
||||
frame_rate=(frame_rate[0]*1000)//frame_rate[1]
|
||||
frame_rate=f"{frame_rate} ({stream['r_frame_rate']})"
|
||||
header=[
|
||||
("Stream_Type",0), # Elementary Stream
|
||||
("MPEG_Type",2), # MPEG-2
|
||||
("iDCT_Algorithm",5), # 64-bit IEEE-1180 Reference
|
||||
("YUVRGB_Scale",int(stream["color_range"]!="tv")),
|
||||
("Luminance_Filter","0,0"),
|
||||
("Clipping","0,0,0,0"),
|
||||
("Aspect_Ratio",stream["display_aspect_ratio"]),
|
||||
("Picture_Size",pict_size),
|
||||
("Field_Operation",0), # Honor Pulldown Flags
|
||||
("Frame_Rate", frame_rate),
|
||||
("Location",f"0,0,0,0"),
|
||||
]
|
||||
for k,v in header:
|
||||
yield f"{k}={v}"
|
||||
|
||||
def gen_d2v(path):
|
||||
yield from make_header(path)
|
||||
yield ""
|
||||
streams,fmt=get_streams(path)
|
||||
stream=[s for s in streams if s['codec_type']=='video'][0]
|
||||
stream['index']=str(stream['index'])
|
||||
yield from make_settings(stream)
|
||||
yield ""
|
||||
line_buffer=[]
|
||||
frames=get_frames(path)
|
||||
prog_bar=tqdm(frames,total=int(fmt['size']),unit_divisor=1024,unit_scale=True,unit="iB",dec="Writing d2v")
|
||||
for line in prog_bar:
|
||||
if 'frame' not in line:
|
||||
continue
|
||||
frame=line['frame']
|
||||
prog_bar.n=min(max(prog_bar.n,int(frame['pkt_pos'])),int(fmt['size']))
|
||||
prog_bar.update(0)
|
||||
if frame['stream_index']!=stream['index']:
|
||||
continue
|
||||
if frame['pict_type']=="I" and line_buffer:
|
||||
yield make_line(line_buffer,stream)
|
||||
line_buffer.clear()
|
||||
line_buffer.append(frame)
|
||||
prog_bar.close()
|
||||
yield None
|
||||
|
||||
def make_d2v(path):
|
||||
outfile=os.path.splitext(os.path.basename(path))[0]
|
||||
outfile=os.path.extsep.join([outfile,"d2v"])
|
||||
a,b=ITT.tee(gen_d2v(path))
|
||||
next(b)
|
||||
with open(outfile,"w") as fh:
|
||||
for line,next_line in zip(a,b):
|
||||
fh.write(line)
|
||||
if next_line is None: # last line, append end marker
|
||||
fh.write(" ff")
|
||||
fh.write("\n")
|
21
ifo_print.h
Normal file
21
ifo_print.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* This file is part of libdvdread.
|
||||
*
|
||||
* libdvdread 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.
|
||||
*
|
||||
* libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
void ifo_print(dvd_reader_t *dvd, int title);
|
||||
void dvdread_print_time(dvd_time_t *dtime);
|
215
ifo_read.h
Normal file
215
ifo_read.h
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>,
|
||||
* Håkan Hjort <d95hjort@dtek.chalmers.se>
|
||||
*
|
||||
* This file is part of libdvdread.
|
||||
*
|
||||
* libdvdread 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.
|
||||
*
|
||||
* libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 (VMGI). This structure is 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_VTS_TMAPT(ifofile);
|
||||
*
|
||||
* Reads in the VTS Time Map Table, this data is only located in the video
|
||||
* title set information file. This fills the ifofile->vts_tmapt structure
|
||||
* and all its substructures. When pressent enables VOBU level time-based
|
||||
* seeking for One_Sequential_PGC_Titles.
|
||||
*/
|
||||
int ifoRead_VTS_TMAPT(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_VTS_TMAPT(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 *);
|
||||
|
683
ifo_types.h
Normal file
683
ifo_types.h
Normal file
|
@ -0,0 +1,683 @@
|
|||
|
||||
/**
|
||||
* 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. */
|
||||
} dvd_time_t;
|
||||
|
||||
/**
|
||||
* Type to store per-command data.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bytes[8];
|
||||
} vm_cmd_t;
|
||||
#define COMMAND_DATA_SIZE 8U
|
||||
|
||||
|
||||
/**
|
||||
* Video Attributes.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char mpeg_version : 2;
|
||||
unsigned char video_format : 2;
|
||||
unsigned char display_aspect_ratio : 2;
|
||||
unsigned char permitted_df : 2;
|
||||
|
||||
unsigned char line21_cc_1 : 1;
|
||||
unsigned char line21_cc_2 : 1;
|
||||
unsigned char unknown1 : 1;
|
||||
unsigned char bit_rate : 1;
|
||||
|
||||
unsigned char picture_size : 2;
|
||||
unsigned char letterboxed : 1;
|
||||
unsigned char film_mode : 1;
|
||||
} video_attr_t;
|
||||
|
||||
/**
|
||||
* Audio Attributes.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char audio_format : 3;
|
||||
unsigned char multichannel_extension : 1;
|
||||
unsigned char lang_type : 2;
|
||||
unsigned char application_mode : 2;
|
||||
|
||||
unsigned char quantization : 2;
|
||||
unsigned char sample_frequency : 2;
|
||||
unsigned char unknown1 : 1;
|
||||
unsigned char channels : 3;
|
||||
uint16_t lang_code;
|
||||
uint8_t lang_extension;
|
||||
uint8_t code_extension;
|
||||
uint8_t unknown3;
|
||||
union {
|
||||
struct {
|
||||
unsigned char unknown4 : 1;
|
||||
unsigned char channel_assignment : 3;
|
||||
unsigned char version : 2;
|
||||
unsigned char mc_intro : 1; /* probably 0: true, 1:false */
|
||||
unsigned char mode : 1; /* Karaoke mode 0: solo 1: duet */
|
||||
} karaoke;
|
||||
struct {
|
||||
unsigned char unknown5 : 4;
|
||||
unsigned char dolby_encoded : 1; /* suitable for surround decoding */
|
||||
unsigned char unknown6 : 3;
|
||||
} surround;
|
||||
} app_info;
|
||||
} audio_attr_t;
|
||||
|
||||
|
||||
/**
|
||||
* MultiChannel Extension
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int zero1 : 7;
|
||||
unsigned int ach0_gme : 1;
|
||||
|
||||
unsigned int zero2 : 7;
|
||||
unsigned int ach1_gme : 1;
|
||||
|
||||
unsigned int zero3 : 4;
|
||||
unsigned int ach2_gv1e : 1;
|
||||
unsigned int ach2_gv2e : 1;
|
||||
unsigned int ach2_gm1e : 1;
|
||||
unsigned int ach2_gm2e : 1;
|
||||
|
||||
unsigned int zero4 : 4;
|
||||
unsigned int ach3_gv1e : 1;
|
||||
unsigned int ach3_gv2e : 1;
|
||||
unsigned int ach3_gmAe : 1;
|
||||
unsigned int ach3_se2e : 1;
|
||||
|
||||
unsigned int zero5 : 4;
|
||||
unsigned int ach4_gv1e : 1;
|
||||
unsigned int ach4_gv2e : 1;
|
||||
unsigned int ach4_gmBe : 1;
|
||||
unsigned int ach4_seBe : 1;
|
||||
uint8_t zero6[19];
|
||||
} multichannel_ext_t;
|
||||
|
||||
|
||||
/**
|
||||
* Subpicture Attributes.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
unsigned char code_mode : 3;
|
||||
unsigned char zero1 : 3;
|
||||
unsigned char type : 2;
|
||||
uint8_t zero2;
|
||||
uint16_t lang_code;
|
||||
uint8_t lang_extension;
|
||||
uint8_t code_extension;
|
||||
} 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;
|
||||
} pgc_command_tbl_t;
|
||||
#define PGC_COMMAND_TBL_SIZE 8U
|
||||
|
||||
/**
|
||||
* PGC Program Map
|
||||
*/
|
||||
typedef uint8_t pgc_program_map_t;
|
||||
|
||||
/**
|
||||
* Cell Playback Information.
|
||||
*/
|
||||
typedef struct {
|
||||
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 zero_1 : 1;
|
||||
unsigned int playback_mode : 1; /**< When set, enter StillMode after each VOBU */
|
||||
unsigned int restricted : 1; /**< ?? drop out of fastforward? */
|
||||
unsigned int cell_type : 5; /** for karaoke, reserved otherwise */
|
||||
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;
|
||||
} 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;
|
||||
} cell_position_t;
|
||||
|
||||
/**
|
||||
* User Operations.
|
||||
*/
|
||||
typedef struct {
|
||||
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;
|
||||
unsigned int subpic_stream_change : 1;
|
||||
unsigned int audio_stream_change : 1;
|
||||
unsigned int pause_on : 1;
|
||||
unsigned int still_off : 1;
|
||||
unsigned int button_select_or_activate : 1;
|
||||
unsigned int resume : 1; /* 16 */
|
||||
|
||||
unsigned int chapter_menu_call : 1; /* 15 */
|
||||
unsigned int angle_menu_call : 1;
|
||||
unsigned int audio_menu_call : 1;
|
||||
unsigned int subpic_menu_call : 1;
|
||||
unsigned int root_menu_call : 1;
|
||||
unsigned int title_menu_call : 1;
|
||||
unsigned int backward_scan : 1;
|
||||
unsigned int forward_scan : 1; /* 8 */
|
||||
|
||||
unsigned int next_pg_search : 1; /* 7 */
|
||||
unsigned int prev_or_top_pg_search : 1;
|
||||
unsigned int time_or_chapter_search : 1;
|
||||
unsigned int go_up : 1;
|
||||
unsigned int stop : 1;
|
||||
unsigned int title_play : 1;
|
||||
unsigned int chapter_search_or_play : 1;
|
||||
unsigned int title_or_time_play : 1; /* 0 */
|
||||
} 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 pg_playback_mode;
|
||||
uint8_t still_time;
|
||||
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;
|
||||
int ref_count;
|
||||
} pgc_t;
|
||||
#define PGC_SIZE 236U
|
||||
|
||||
/**
|
||||
* Program Chain Information Search Pointer.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t entry_id;
|
||||
unsigned int block_mode : 2;
|
||||
unsigned int block_type : 2;
|
||||
unsigned int zero_1 : 4;
|
||||
uint16_t ptl_id_mask;
|
||||
uint32_t pgc_start_byte;
|
||||
pgc_t *pgc;
|
||||
} pgci_srp_t;
|
||||
#define PGCI_SRP_SIZE 8U
|
||||
|
||||
/**
|
||||
* 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;
|
||||
int ref_count;
|
||||
} pgcit_t;
|
||||
#define PGCIT_SIZE 8U
|
||||
|
||||
/**
|
||||
* Menu PGCI Language Unit.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t lang_code;
|
||||
uint8_t lang_extension;
|
||||
uint8_t exists;
|
||||
uint32_t lang_start_byte;
|
||||
pgcit_t *pgcit;
|
||||
} pgci_lu_t;
|
||||
#define PGCI_LU_SIZE 8U
|
||||
|
||||
/**
|
||||
* Menu PGCI Unit Table.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t nr_of_lus;
|
||||
uint16_t zero_1;
|
||||
uint32_t last_byte;
|
||||
pgci_lu_t *lu;
|
||||
} pgci_ut_t;
|
||||
#define PGCI_UT_SIZE 8U
|
||||
|
||||
/**
|
||||
* 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;
|
||||
} 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; /* No explicit size given. */
|
||||
} c_adt_t;
|
||||
#define C_ADT_SIZE 8U
|
||||
|
||||
/**
|
||||
* VOBU Address Map.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t last_byte;
|
||||
uint32_t *vobu_start_sectors;
|
||||
} vobu_admap_t;
|
||||
#define VOBU_ADMAP_SIZE 4U
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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? */
|
||||
} vmgi_mat_t;
|
||||
|
||||
typedef struct {
|
||||
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 */
|
||||
} 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;
|
||||
} 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;
|
||||
} tt_srpt_t;
|
||||
#define TT_SRPT_SIZE 8U
|
||||
|
||||
|
||||
/**
|
||||
* Parental Management Information Unit Table.
|
||||
* Level 1 (US: G), ..., 7 (US: NC-17), 8
|
||||
*/
|
||||
#define PTL_MAIT_NUM_LEVEL 8
|
||||
typedef uint16_t pf_level_t[PTL_MAIT_NUM_LEVEL];
|
||||
|
||||
/**
|
||||
* 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;
|
||||
pf_level_t *pf_ptl_mai; /* table of (nr_of_vtss + 1), video_ts is first */
|
||||
} ptl_mait_country_t;
|
||||
#define PTL_MAIT_COUNTRY_SIZE 8U
|
||||
|
||||
/**
|
||||
* 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;
|
||||
} ptl_mait_t;
|
||||
#define PTL_MAIT_SIZE 8U
|
||||
|
||||
/**
|
||||
* 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];
|
||||
} vts_attributes_t;
|
||||
#define VTS_ATTRIBUTES_SIZE 542U
|
||||
#define VTS_ATTRIBUTES_MIN_SIZE 356U
|
||||
|
||||
/**
|
||||
* Video Title Set Attribute Table.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t nr_of_vtss;
|
||||
uint16_t zero_1;
|
||||
uint32_t last_byte;
|
||||
vts_attributes_t *vts;
|
||||
uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes */
|
||||
} vts_atrt_t;
|
||||
#define VTS_ATRT_SIZE 8U
|
||||
|
||||
/**
|
||||
* 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) */
|
||||
} txtdt_t;
|
||||
|
||||
/**
|
||||
* Text Data Language Unit. (Incomplete)
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t lang_code;
|
||||
uint8_t zero_1;
|
||||
uint8_t char_set; /* 0x00 reserved Unicode, 0x01 ISO 646, 0x10 JIS Roman & JIS Kanji, 0x11 ISO 8859-1, 0x12 Shift JIS Kanji */
|
||||
uint32_t txtdt_start_byte; /* prt, rel start of vmg_txtdt_mgi */
|
||||
txtdt_t *txtdt;
|
||||
} txtdt_lu_t;
|
||||
#define TXTDT_LU_SIZE 8U
|
||||
|
||||
/**
|
||||
* Text Data Manager Information. (Incomplete)
|
||||
*/
|
||||
typedef struct {
|
||||
char disc_name[12];
|
||||
uint16_t zero_1;
|
||||
uint16_t nr_of_language_units;
|
||||
uint32_t last_byte;
|
||||
txtdt_lu_t *lu;
|
||||
} txtdt_mgi_t;
|
||||
#define TXTDT_MGI_SIZE 20U
|
||||
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
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];
|
||||
uint16_t zero_21;
|
||||
multichannel_ext_t vts_mu_audio_attr[8];
|
||||
/* XXX: how much 'padding' here, if any? */
|
||||
} vtsi_mat_t;
|
||||
|
||||
/**
|
||||
* PartOfTitle Unit Information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t pgcn;
|
||||
uint16_t pgn;
|
||||
} ptt_info_t;
|
||||
|
||||
/**
|
||||
* PartOfTitle Information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t nr_of_ptts;
|
||||
ptt_info_t *ptt;
|
||||
} ttu_t;
|
||||
|
||||
/**
|
||||
* PartOfTitle Search Pointer Table.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t nr_of_srpts;
|
||||
uint16_t zero_1;
|
||||
uint32_t last_byte;
|
||||
ttu_t *title;
|
||||
uint32_t *ttu_offset; /* offset table for each ttu */
|
||||
} vts_ptt_srpt_t;
|
||||
#define VTS_PTT_SRPT_SIZE 8U
|
||||
|
||||
|
||||
/**
|
||||
* Time Map Entry.
|
||||
*/
|
||||
/* Should this be bit field at all or just the uint32_t? */
|
||||
typedef uint32_t map_ent_t;
|
||||
|
||||
/**
|
||||
* Time Map.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t tmu; /* Time unit, in seconds */
|
||||
uint8_t zero_1;
|
||||
uint16_t nr_of_entries;
|
||||
map_ent_t *map_ent;
|
||||
} vts_tmap_t;
|
||||
#define VTS_TMAP_SIZE 4U
|
||||
|
||||
/**
|
||||
* Time Map Table.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t nr_of_tmaps;
|
||||
uint16_t zero_1;
|
||||
uint32_t last_byte;
|
||||
vts_tmap_t *tmap;
|
||||
uint32_t *tmap_offset; /* offset table for each tmap */
|
||||
} vts_tmapt_t;
|
||||
#define VTS_TMAPT_SIZE 8U
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
/* 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;
|
||||
vts_tmapt_t *vts_tmapt;
|
||||
c_adt_t *vts_c_adt;
|
||||
vobu_admap_t *vts_vobu_admap;
|
||||
} ifo_handle_t;
|
38
nav_print.h
Normal file
38
nav_print.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
|
||||
* Håkan Hjort <d95hjort@dtek.chalmers.se>
|
||||
*
|
||||
* This file is part of libdvdread.
|
||||
*
|
||||
* libdvdread 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.
|
||||
*
|
||||
* libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pretty printing of the NAV packets, PCI and DSI structs.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prints information contained in the PCI to stdout.
|
||||
*
|
||||
* @param pci Pointer to the PCI data structure to be printed.
|
||||
*/
|
||||
void navPrint_PCI(pci_t *);
|
||||
|
||||
/**
|
||||
* Prints information contained in the DSI to stdout.
|
||||
*
|
||||
* @param dsi Pointer to the DSI data structure to be printed.
|
||||
*/
|
||||
void navPrint_DSI(dsi_t *);
|
40
nav_read.h
Normal file
40
nav_read.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se>.
|
||||
*
|
||||
* This file is part of libdvdread.
|
||||
*
|
||||
* libdvdread 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.
|
||||
*
|
||||
* libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parsing of NAV data, PCI and DSI parts.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reads the PCI packet data pointed to into th pci struct.
|
||||
*
|
||||
* @param pci Pointer to the PCI data structure to be filled in.
|
||||
* @param bufffer Pointer to the buffer of the on disc PCI data.
|
||||
*/
|
||||
void navRead_PCI(pci_t *, unsigned char *);
|
||||
|
||||
/**
|
||||
* Reads the DSI packet data pointed to into dsi struct.
|
||||
*
|
||||
* @param dsi Pointer to the DSI data structure to be filled in.
|
||||
* @param bufffer Pointer to the buffer of the on disc DSI data.
|
||||
*/
|
||||
void navRead_DSI(dsi_t *, unsigned char *);
|
||||
|
235
nav_types.h
Normal file
235
nav_types.h
Normal file
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@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@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* 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
|
||||
|
||||
/**
|
||||
* PCI General Information
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t nv_pck_lbn; /**< sector address of this nav pack */
|
||||
uint16_t vobu_cat; /**< 'category' of vobu */
|
||||
uint16_t zero1; /**< reserved */
|
||||
user_ops_t vobu_uop_ctl; /**< UOP of vobu */
|
||||
uint32_t vobu_s_ptm; /**< start presentation time of vobu */
|
||||
uint32_t vobu_e_ptm; /**< end presentation time of vobu */
|
||||
uint32_t vobu_se_e_ptm; /**< end ptm of sequence end in vobu */
|
||||
dvd_time_t e_eltm; /**< Cell elapsed time */
|
||||
char vobu_isrc[32];
|
||||
} pci_gi_t;
|
||||
|
||||
/**
|
||||
* Non Seamless Angle Information
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t nsml_agl_dsta[9]; /**< address of destination vobu in AGL_C#n */
|
||||
} nsml_agli_t;
|
||||
|
||||
/**
|
||||
* Highlight General Information
|
||||
*
|
||||
* For btngrX_dsp_ty the bits have the following meaning:
|
||||
* 000b: normal 4/3 only buttons
|
||||
* XX1b: wide (16/9) buttons
|
||||
* X1Xb: letterbox buttons
|
||||
* 1XXb: pan&scan buttons
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t hli_ss; /**< status, only low 2 bits 0: no buttons, 1: different 2: equal 3: eual except for button cmds */
|
||||
uint32_t hli_s_ptm; /**< start ptm of hli */
|
||||
uint32_t hli_e_ptm; /**< end ptm of hli */
|
||||
uint32_t btn_se_e_ptm; /**< end ptm of button select */
|
||||
unsigned int zero1 : 2; /**< reserved */
|
||||
unsigned int btngr_ns : 2; /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */
|
||||
unsigned int zero2 : 1; /**< reserved */
|
||||
unsigned int btngr1_dsp_ty : 3; /**< display type of subpic stream for button group 1 */
|
||||
unsigned int zero3 : 1; /**< reserved */
|
||||
unsigned int btngr2_dsp_ty : 3; /**< display type of subpic stream for button group 2 */
|
||||
unsigned int zero4 : 1; /**< reserved */
|
||||
unsigned int btngr3_dsp_ty : 3; /**< display type of subpic stream for button group 3 */
|
||||
uint8_t btn_ofn; /**< button offset number range 0-255 */
|
||||
uint8_t btn_ns; /**< number of valid buttons <= 36/18/12 (low 6 bits) */
|
||||
uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */
|
||||
uint8_t zero5; /**< reserved */
|
||||
uint8_t fosl_btnn; /**< forcedly selected button (low 6 bits) */
|
||||
uint8_t foac_btnn; /**< forcedly activated button (low 6 bits) */
|
||||
} hl_gi_t;
|
||||
|
||||
|
||||
/**
|
||||
* Button Color Information Table
|
||||
* Each entry beeing a 32bit word that contains the color indexs and alpha
|
||||
* values to use. They are all represented by 4 bit number and stored
|
||||
* like this [Ci3, Ci2, Ci1, Ci0, A3, A2, A1, A0]. The actual palette
|
||||
* that the indexes reference is in the PGC.
|
||||
* @TODO split the uint32_t into a struct
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t btn_coli[3][2]; /**< [button color number-1][select:0/action:1] */
|
||||
} btn_colit_t;
|
||||
|
||||
/**
|
||||
* Button Information
|
||||
*
|
||||
* NOTE: I've had to change the structure from the disk layout to get
|
||||
* the packing to work with Sun's Forte C compiler.
|
||||
* The 4 and 7 bytes are 'rotated' was: ABC DEF GHIJ is: ABCG DEFH IJ
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int btn_coln : 2; /**< button color number */
|
||||
unsigned int x_start : 10; /**< x start offset within the overlay */
|
||||
unsigned int zero1 : 2; /**< reserved */
|
||||
unsigned int x_end : 10; /**< x end offset within the overlay */
|
||||
|
||||
unsigned int auto_action_mode : 2; /**< 0: no, 1: activated if selected */
|
||||
unsigned int y_start : 10; /**< y start offset within the overlay */
|
||||
unsigned int zero2 : 2; /**< reserved */
|
||||
unsigned int y_end : 10; /**< y end offset within the overlay */
|
||||
|
||||
unsigned int zero3 : 2; /**< reserved */
|
||||
unsigned int up : 6; /**< button index when pressing up */
|
||||
unsigned int zero4 : 2; /**< reserved */
|
||||
unsigned int down : 6; /**< button index when pressing down */
|
||||
unsigned int zero5 : 2; /**< reserved */
|
||||
unsigned int left : 6; /**< button index when pressing left */
|
||||
unsigned int zero6 : 2; /**< reserved */
|
||||
unsigned int right : 6; /**< button index when pressing right */
|
||||
vm_cmd_t cmd;
|
||||
} btni_t;
|
||||
|
||||
/**
|
||||
* Highlight Information
|
||||
*/
|
||||
typedef struct {
|
||||
hl_gi_t hl_gi;
|
||||
btn_colit_t btn_colit;
|
||||
btni_t btnit[36];
|
||||
} hli_t;
|
||||
|
||||
/**
|
||||
* PCI packet
|
||||
*/
|
||||
typedef struct {
|
||||
pci_gi_t pci_gi;
|
||||
nsml_agli_t nsml_agli;
|
||||
hli_t hli;
|
||||
uint8_t zero1[189];
|
||||
} pci_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* DSI General Information
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t nv_pck_scr;
|
||||
uint32_t nv_pck_lbn; /**< sector address of this nav pack */
|
||||
uint32_t vobu_ea; /**< end address of this VOBU */
|
||||
uint32_t vobu_1stref_ea; /**< end address of the 1st reference image */
|
||||
uint32_t vobu_2ndref_ea; /**< end address of the 2nd reference image */
|
||||
uint32_t vobu_3rdref_ea; /**< end address of the 3rd reference image */
|
||||
uint16_t vobu_vob_idn; /**< VOB Id number that this VOBU is part of */
|
||||
uint8_t zero1; /**< reserved */
|
||||
uint8_t vobu_c_idn; /**< Cell Id number that this VOBU is part of */
|
||||
dvd_time_t c_eltm; /**< Cell elapsed time */
|
||||
} dsi_gi_t;
|
||||
|
||||
/**
|
||||
* Seamless Playback Information
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t category; /**< 'category' of seamless VOBU */
|
||||
uint32_t ilvu_ea; /**< end address of interleaved Unit */
|
||||
uint32_t ilvu_sa; /**< start address of next interleaved unit */
|
||||
uint16_t size; /**< size of next interleaved unit */
|
||||
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];
|
||||
} sml_pbi_t;
|
||||
|
||||
/**
|
||||
* Seamless Angle Information for one angle
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t address; /**< offset to next ILVU, high bit is before/after */
|
||||
uint16_t size; /**< byte size of the ILVU pointed to by address */
|
||||
} sml_agl_data_t;
|
||||
|
||||
/**
|
||||
* Seamless Angle Information
|
||||
*/
|
||||
typedef struct {
|
||||
sml_agl_data_t data[9];
|
||||
} 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;
|
||||
} vobu_sri_t;
|
||||
|
||||
#define SRI_END_OF_CELL 0x3fffffff
|
||||
|
||||
/**
|
||||
* Synchronous Information
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t a_synca[8]; /**< offset to first audio packet for this VOBU */
|
||||
uint32_t sp_synca[32]; /**< offset to first subpicture packet */
|
||||
} 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];
|
||||
} dsi_t;
|
63
vob_demux.py
Normal file
63
vob_demux.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
import sys
|
||||
import os
|
||||
import json
|
||||
import subprocess as SP
|
||||
|
||||
|
||||
def get_streams(path):
|
||||
proc=SP.Popen([
|
||||
"ffprobe",
|
||||
"-probesize", str(0x7fffffff),
|
||||
"-analyzeduration", str(0x7fffffff),
|
||||
"-v","fatal",
|
||||
"-i",path,
|
||||
"-show_streams",
|
||||
"-show_format",
|
||||
"-print_format","json"
|
||||
],stdout=SP.PIPE,stdin=SP.DEVNULL,bufsize=0)
|
||||
data=json.load(proc.stdout)
|
||||
ret=proc.wait()
|
||||
if ret!=0:
|
||||
return [],{}
|
||||
return data['streams'],data['format']
|
||||
|
||||
types={
|
||||
'mpeg2video': 'm2v',
|
||||
'ac3': 'ac3',
|
||||
'dvd_subtitle': 'sup',
|
||||
}
|
||||
|
||||
def demux(path):
|
||||
folder=os.path.dirname(path)
|
||||
basename=os.path.splitext(os.path.basename(path))[0]
|
||||
streams,fmt=get_streams(path)
|
||||
cmd=[
|
||||
"ffmpeg",
|
||||
"-y",
|
||||
"-strict","-2",
|
||||
"-fflags","+genpts",
|
||||
"-probesize", str(0x7fffffff),
|
||||
"-analyzeduration", str(0x7fffffff),
|
||||
"-i",path,
|
||||
"-scodec","copy",
|
||||
"-vcodec","copy",
|
||||
"-acodec","copy",
|
||||
]
|
||||
need_ffmpeg=False
|
||||
for stream in streams:
|
||||
codec=stream['codec_name']
|
||||
ext=types.get(codec,codec)
|
||||
idx=stream['index']
|
||||
hex_id=stream['id']
|
||||
codec_name=stream['codec_long_name']
|
||||
outfile=os.path.join(folder,f"{basename}_{idx}_{hex_id}")
|
||||
if codec=="dvd_subtitle":
|
||||
SP.check_call([
|
||||
"mencoder",path,"-vobsuboutindex",str(idx),"-vobsubout", outfile,"-nosound","-ovc", "copy", "-o",os.devnull
|
||||
])
|
||||
continue
|
||||
print(idx,hex_id,codec_name,codec)
|
||||
cmd+=["-map",f"0:#{hex_id}",outfile+f".{ext}"]
|
||||
need_ffmpeg=True
|
||||
if need_ffmpeg:
|
||||
SP.check_call(cmd)
|
Loading…
Reference in a new issue