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