* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
- * $Id: input_dvd.c,v 1.19 2001/02/22 08:44:45 stef Exp $
+ * $Id: input_dvd.c,v 1.29 2001/03/05 00:40:06 stef Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
-#define MODULE_NAME dvd
-#include "modules_inner.h"
-
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
+#ifdef HAVE_CSS
+#define MODULE_NAME dvd-css
+#else /* HAVE_CSS */
+#define MODULE_NAME dvd-nocss
+#endif /* HAVE_CSS */
+#include "modules_inner.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "input_ext-dec.h"
#include "input.h"
-#include "input_netlist.h"
+#include "dvd_netlist.h"
#include "dvd_ifo.h"
#include "dvd_css.h"
#include "input_dvd.h"
{
char p_code[3];
char p_lang_long[20];
-} lang_tbl[] =
- {
+}
+lang_tbl[] =
+{
/* The ISO 639 language codes.
* Language names with * prefix are not spelled in their own language
*/
- {" ", "Not Specified"},
- {"aa", "*Afar"},
- {"ab", "*Abkhazian"},
- {"af", "*Afrikaans"},
- {"am", "*Amharic"},
- {"ar", "*Arabic"},
- {"as", "*Assamese"},
- {"ay", "*Aymara"},
- {"az", "*Azerbaijani"},
- {"ba", "*Bashkir"},
- {"be", "*Byelorussian"},
- {"bg", "*Bulgarian"},
- {"bh", "*Bihari"},
- {"bi", "*Bislama"},
- {"bn", "*Bengali; Bangla"},
- {"bo", "*Tibetan"},
- {"br", "*Breton"},
- {"ca", "*Catalan"},
- {"co", "*Corsican"},
- {"cs", "*Czech(Ceske)"},
- {"cy", "*Welsh"},
- {"da", "Dansk"},
- {"de", "Deutsch"},
- {"dz", "*Bhutani"},
- {"el", "*Greek"},
- {"en", "English"},
- {"eo", "*Esperanto"},
- {"es", "Espanol"},
- {"et", "*Estonian"},
- {"eu", "*Basque"},
- {"fa", "*Persian"},
- {"fi", "Suomi"},
- {"fj", "*Fiji"},
- {"fo", "*Faroese"},
- {"fr", "Francais"},
- {"fy", "*Frisian"},
- {"ga", "*Irish"},
- {"gd", "*Scots Gaelic"},
- {"gl", "*Galician"},
- {"gn", "*Guarani"},
- {"gu", "*Gujarati"},
- {"ha", "*Hausa"},
- {"he", "*Hebrew"}, // formerly iw
- {"hi", "*Hindi"},
- {"hr", "Hrvatski"}, // Croatian
- {"hu", "Magyar"},
- {"hy", "*Armenian"},
- {"ia", "*Interlingua"},
- {"id", "*Indonesian"}, // formerly in
- {"ie", "*Interlingue"},
- {"ik", "*Inupiak"},
- {"in", "*Indonesian"}, // replaced by id
- {"is", "Islenska"},
- {"it", "Italiano"},
- {"iu", "*Inuktitut"},
- {"iw", "*Hebrew"}, // replaced by he
- {"ja", "*Japanese"},
- {"ji", "*Yiddish"}, // replaced by yi
- {"jw", "*Javanese"},
- {"ka", "*Georgian"},
- {"kk", "*Kazakh"},
- {"kl", "*Greenlandic"},
- {"km", "*Cambodian"},
- {"kn", "*Kannada"},
- {"ko", "*Korean"},
- {"ks", "*Kashmiri"},
- {"ku", "*Kurdish"},
- {"ky", "*Kirghiz"},
- {"la", "*Latin"},
- {"ln", "*Lingala"},
- {"lo", "*Laothian"},
- {"lt", "*Lithuanian"},
- {"lv", "*Latvian, Lettish"},
- {"mg", "*Malagasy"},
- {"mi", "*Maori"},
- {"mk", "*Macedonian"},
- {"ml", "*Malayalam"},
- {"mn", "*Mongolian"},
- {"mo", "*Moldavian"},
- {"mr", "*Marathi"},
- {"ms", "*Malay"},
- {"mt", "*Maltese"},
- {"my", "*Burmese"},
- {"na", "*Nauru"},
- {"ne", "*Nepali"},
- {"nl", "Nederlands"},
- {"no", "Norsk"},
- {"oc", "*Occitan"},
- {"om", "*(Afan) Oromo"},
- {"or", "*Oriya"},
- {"pa", "*Punjabi"},
- {"pl", "*Polish"},
- {"ps", "*Pashto, Pushto"},
- {"pt", "Portugues"},
- {"qu", "*Quechua"},
- {"rm", "*Rhaeto-Romance"},
- {"rn", "*Kirundi"},
- {"ro", "*Romanian"},
- {"ru", "*Russian"},
- {"rw", "*Kinyarwanda"},
- {"sa", "*Sanskrit"},
- {"sd", "*Sindhi"},
- {"sg", "*Sangho"},
- {"sh", "*Serbo-Croatian"},
- {"si", "*Sinhalese"},
- {"sk", "*Slovak"},
- {"sl", "*Slovenian"},
- {"sm", "*Samoan"},
- {"sn", "*Shona"},
- {"so", "*Somali"},
- {"sq", "*Albanian"},
- {"sr", "*Serbian"},
- {"ss", "*Siswati"},
- {"st", "*Sesotho"},
- {"su", "*Sundanese"},
- {"sv", "Svenska"},
- {"sw", "*Swahili"},
- {"ta", "*Tamil"},
- {"te", "*Telugu"},
- {"tg", "*Tajik"},
- {"th", "*Thai"},
- {"ti", "*Tigrinya"},
- {"tk", "*Turkmen"},
- {"tl", "*Tagalog"},
- {"tn", "*Setswana"},
- {"to", "*Tonga"},
- {"tr", "*Turkish"},
- {"ts", "*Tsonga"},
- {"tt", "*Tatar"},
- {"tw", "*Twi"},
- {"ug", "*Uighur"},
- {"uk", "*Ukrainian"},
- {"ur", "*Urdu"},
- {"uz", "*Uzbek"},
- {"vi", "*Vietnamese"},
- {"vo", "*Volapuk"},
- {"wo", "*Wolof"},
- {"xh", "*Xhosa"},
- {"yi", "*Yiddish"}, // formerly ji
- {"yo", "*Yoruba"},
- {"za", "*Zhuang"},
- {"zh", "*Chinese"},
- {"zu", "*Zulu"},
- {"\0", ""}
- };
+ { " ", "Not Specified" },
+ { "aa", "*Afar" },
+ { "ab", "*Abkhazian" },
+ { "af", "*Afrikaans" },
+ { "am", "*Amharic" },
+ { "ar", "*Arabic" },
+ { "as", "*Assamese" },
+ { "ay", "*Aymara" },
+ { "az", "*Azerbaijani" },
+ { "ba", "*Bashkir" },
+ { "be", "*Byelorussian" },
+ { "bg", "*Bulgarian" },
+ { "bh", "*Bihari" },
+ { "bi", "*Bislama" },
+ { "bn", "*Bengali; Bangla" },
+ { "bo", "*Tibetan" },
+ { "br", "*Breton" },
+ { "ca", "*Catalan" },
+ { "co", "*Corsican" },
+ { "cs", "*Czech(Ceske)" },
+ { "cy", "*Welsh" },
+ { "da", "Dansk" },
+ { "de", "Deutsch" },
+ { "dz", "*Bhutani" },
+ { "el", "*Greek" },
+ { "en", "English" },
+ { "eo", "*Esperanto" },
+ { "es", "Espanol" },
+ { "et", "*Estonian" },
+ { "eu", "*Basque" },
+ { "fa", "*Persian" },
+ { "fi", "Suomi" },
+ { "fj", "*Fiji" },
+ { "fo", "*Faroese" },
+ { "fr", "Francais" },
+ { "fy", "*Frisian" },
+ { "ga", "*Irish" },
+ { "gd", "*Scots Gaelic" },
+ { "gl", "*Galician" },
+ { "gn", "*Guarani" },
+ { "gu", "*Gujarati" },
+ { "ha", "*Hausa" },
+ { "he", "*Hebrew" }, /* formerly iw */
+ { "hi", "*Hindi" },
+ { "hr", "Hrvatski" }, /* Croatian */
+ { "hu", "Magyar" },
+ { "hy", "*Armenian" },
+ { "ia", "*Interlingua" },
+ { "id", "*Indonesian" }, /* formerly in */
+ { "ie", "*Interlingue" },
+ { "ik", "*Inupiak" },
+ { "in", "*Indonesian" }, /* replaced by id */
+ { "is", "Islenska" },
+ { "it", "Italiano" },
+ { "iu", "*Inuktitut" },
+ { "iw", "*Hebrew" }, /* replaced by he */
+ { "ja", "*Japanese" },
+ { "ji", "*Yiddish" }, /* replaced by yi */
+ { "jw", "*Javanese" },
+ { "ka", "*Georgian" },
+ { "kk", "*Kazakh" },
+ { "kl", "*Greenlandic" },
+ { "km", "*Cambodian" },
+ { "kn", "*Kannada" },
+ { "ko", "*Korean" },
+ { "ks", "*Kashmiri" },
+ { "ku", "*Kurdish" },
+ { "ky", "*Kirghiz" },
+ { "la", "*Latin" },
+ { "ln", "*Lingala" },
+ { "lo", "*Laothian" },
+ { "lt", "*Lithuanian" },
+ { "lv", "*Latvian, Lettish" },
+ { "mg", "*Malagasy" },
+ { "mi", "*Maori" },
+ { "mk", "*Macedonian" },
+ { "ml", "*Malayalam" },
+ { "mn", "*Mongolian" },
+ { "mo", "*Moldavian" },
+ { "mr", "*Marathi" },
+ { "ms", "*Malay" },
+ { "mt", "*Maltese" },
+ { "my", "*Burmese" },
+ { "na", "*Nauru" },
+ { "ne", "*Nepali" },
+ { "nl", "Nederlands" },
+ { "no", "Norsk" },
+ { "oc", "*Occitan" },
+ { "om", "*(Afan) Oromo" },
+ { "or", "*Oriya" },
+ { "pa", "*Punjabi" },
+ { "pl", "*Polish" },
+ { "ps", "*Pashto, Pushto" },
+ { "pt", "Portugues" },
+ { "qu", "*Quechua" },
+ { "rm", "*Rhaeto-Romance" },
+ { "rn", "*Kirundi" },
+ { "ro", "*Romanian" },
+ { "ru", "*Russian" },
+ { "rw", "*Kinyarwanda" },
+ { "sa", "*Sanskrit" },
+ { "sd", "*Sindhi" },
+ { "sg", "*Sangho" },
+ { "sh", "*Serbo-Croatian" },
+ { "si", "*Sinhalese" },
+ { "sk", "*Slovak" },
+ { "sl", "*Slovenian" },
+ { "sm", "*Samoan" },
+ { "sn", "*Shona" },
+ { "so", "*Somali" },
+ { "sq", "*Albanian" },
+ { "sr", "*Serbian" },
+ { "ss", "*Siswati" },
+ { "st", "*Sesotho" },
+ { "su", "*Sundanese" },
+ { "sv", "Svenska" },
+ { "sw", "*Swahili" },
+ { "ta", "*Tamil" },
+ { "te", "*Telugu" },
+ { "tg", "*Tajik" },
+ { "th", "*Thai" },
+ { "ti", "*Tigrinya" },
+ { "tk", "*Turkmen" },
+ { "tl", "*Tagalog" },
+ { "tn", "*Setswana" },
+ { "to", "*Tonga" },
+ { "tr", "*Turkish" },
+ { "ts", "*Tsonga" },
+ { "tt", "*Tatar" },
+ { "tw", "*Twi" },
+ { "ug", "*Uighur" },
+ { "uk", "*Ukrainian" },
+ { "ur", "*Urdu" },
+ { "uz", "*Uzbek" },
+ { "vi", "*Vietnamese" },
+ { "vo", "*Volapuk" },
+ { "wo", "*Wolof" },
+ { "xh", "*Xhosa" },
+ { "yi", "*Yiddish" }, /* formerly ji */
+ { "yo", "*Yoruba" },
+ { "za", "*Zhuang" },
+ { "zh", "*Chinese" },
+ { "zu", "*Zulu" },
+ { "\0", "" }
+};
/*****************************************************************************
* Local prototypes
input.pf_read = DVDRead;
input.pf_set_area = DVDSetArea;
input.pf_demux = input_DemuxPS;
- input.pf_new_packet = input_NetlistNewPacket;
- input.pf_new_pes = input_NetlistNewPES;
- input.pf_delete_packet = input_NetlistDeletePacket;
- input.pf_delete_pes = input_NetlistDeletePES;
+ input.pf_new_packet = DVDNewPacket;
+ input.pf_new_pes = DVDNewPES;
+ input.pf_delete_packet = DVDDeletePacket;
+ input.pf_delete_pes = DVDDeletePES;
input.pf_rewind = DVDRewind;
input.pf_seek = DVDSeek;
#undef input
if( TestMethod( INPUT_METHOD_VAR, "dvd" ) )
{
+#ifdef HAVE_CSS
return( 999 );
+#else /* HAVE_CSS */
+ return( 998 );
+#endif /* HAVE_CSS */
}
if( ( strlen(psz_name) > 4 ) && !strncasecmp( psz_name, "dvd:", 4 ) )
{
/* If the user specified "dvd:" then it's probably a DVD */
+#ifdef HAVE_CSS
i_score = 100;
+#else /* HAVE_CSS */
+ i_score = 90;
+#endif /* HAVE_CSS */
psz_name += 4;
}
return CSSTest( p_input->i_handle );
}
+
+/*****************************************************************************
+ * DVDFindSector: find cell index in adress map from index in
+ * information table program map and give corresponding sectors.
+ *****************************************************************************/
+static int DVDFindSector( thread_dvd_data_t * p_dvd )
+{
+ pgc_t * p_pgc;
+ int i_cell;
+ int i_index;
+
+ p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc;
+
+ i_index = p_dvd->i_prg_cell - 1;
+
+ do {
+ if( i_index++ > p_dvd->i_prg_cell )
+ {
+ return -1;
+ }
+
+ i_cell = p_dvd->i_cell + 1;
+
+ while( ( ( p_pgc->p_cell_pos_inf[i_index].i_vob_id !=
+ p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id ) ||
+ ( p_pgc->p_cell_pos_inf[i_index].i_cell_id !=
+ p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id ) ) &&
+ ( i_cell < ( p_dvd->ifo.vts.c_adt.i_cell_nb ) ) )
+ {
+ i_cell++;
+ }
+
+ } while( i_cell == ( p_dvd->ifo.vts.c_adt.i_cell_nb ) );
+
+ p_dvd->i_cell = i_cell;
+ p_dvd->i_prg_cell = i_index;
+
+ /* Find start and end sectors of new cell */
+ p_dvd->i_sector = MAX(
+ p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_ssector,
+ p_pgc->p_cell_play_inf[i_index].i_entry_sector );
+ p_dvd->i_end_sector = MIN(
+ p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_esector,
+ p_pgc->p_cell_play_inf[i_index].i_lsector );
+
+//intf_WarnMsg( 3, "cell: %d index: %d sector1: %x sector2: %x end1: %x end2: %x", i_cell, i_index, p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_ssector, p_pgc->p_cell_play_inf[i_index].i_entry_sector, p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_esector,p_pgc->p_cell_play_inf[i_index].i_lsector );
+
+ return 0;
+}
+
/*****************************************************************************
* DVDChapterSelect: find the cell corresponding to requested chapter
+ * When called to find chapter 1, also sets title size and end.
*****************************************************************************/
static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
{
pgc_t * p_pgc;
- int i_start_cell;
- int i_end_cell;
- int i_index;
- int i_cell;
- p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[0].pgc;
+ p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc;
/* Find cell index in Program chain for current chapter */
- i_index = p_pgc->prg_map.pi_entry_cell[i_chapter-1] - 1;
+ p_dvd->i_prg_cell = p_pgc->prg_map.pi_entry_cell[i_chapter-1] - 1;
+ p_dvd->i_cell = -1;
/* Search for cell_index in cell adress_table */
- i_cell = 0;
- while( p_pgc->p_cell_pos_inf[i_index].i_vob_id >
- p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id )
- {
- i_cell++;
- }
- while( p_pgc->p_cell_pos_inf[i_index].i_cell_id >
- p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id )
- {
- i_cell++;
- }
+ DVDFindSector( p_dvd );
- i_start_cell = i_cell;
+ /* initialize navigation parameters */
+ p_dvd->i_sector = p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_ssector;
+ p_dvd->i_end_sector =
+ p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector;
- p_dvd->i_start = p_dvd->ifo.vts.i_pos + DVD_LB_SIZE *
- (off_t)( p_dvd->ifo.vts.mat.i_tt_vobs_ssector +
- p_dvd->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector );
+ /* start is : beginning of vts vobs + offset to vob x */
+ p_dvd->i_start = p_dvd->i_title_start +
+ DVD_LB_SIZE * (off_t)( p_dvd->i_sector );
- if( i_chapter == 1 )
- {
- i_end_cell = i_start_cell + p_pgc->i_cell_nb - 1;
- p_dvd->i_size = (off_t)DVD_LB_SIZE *
- ( p_dvd->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_esector -
- p_dvd->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector + 1 );
- p_dvd->i_chapter_nb = p_pgc->i_cell_nb;
- intf_WarnMsg( 3, "DVD: Start cell: %d End Cell: %d",
- i_start_cell, i_end_cell );
- }
+ /* Position the fd pointer on the right address */
+ p_dvd->i_start = lseek( p_dvd->i_fd, p_dvd->i_start, SEEK_SET );
+
+ p_dvd->i_chapter = i_chapter;
return 0;
}
int i_title, int i_chapter,
int i_audio, int i_spu )
{
- thread_dvd_data_t * p_method;
+ thread_dvd_data_t * p_dvd;
es_descriptor_t * p_es;
int i_index;
int i_nb;
u8 i;
boolean_t b_last;
- p_method = (thread_dvd_data_t*)p_input->p_plugin_data;
+ p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data;
vlc_mutex_lock( &p_input->stream.stream_lock );
if( i_title >= 0 )
{
+
/*
* We have to load all title information
*/
/* Change the default area */
p_input->stream.p_selected_area = p_input->stream.pp_areas[i_title];
- /* Ifo VTS, and CSS reading */
- p_method->ifo.i_title = i_title;
- IfoReadVTS( &(p_method->ifo) );
- intf_WarnMsg( 2, "Ifo: VTS initialized" );
+ /* title number: it is not vts nb! */
+ p_dvd->i_title = i_title;
+
+ /* title position inside the selected vts */
+ p_dvd->i_vts_title =
+ p_dvd->ifo.vmg.ptt_srpt.p_tts[i_title-1].i_vts_ttn;
+
+ /* vts number */
+ p_dvd->ifo.i_title = i_title;
+
+ /* ifo vts */
+ IfoReadVTS( &(p_dvd->ifo) );
+ intf_WarnMsg( 2, "ifo info: vts initialized" );
- if( p_method->b_encrypted )
+ /* css title key for current vts */
+ if( p_dvd->b_encrypted )
{
- p_method->css.i_title = i_title;
- p_method->css.i_title_pos =
- p_method->ifo.vts.i_pos +
- p_method->ifo.vts.mat.i_tt_vobs_ssector * DVD_LB_SIZE;
- CSSGetKey( &(p_method->css) );
- intf_WarnMsg( 2, "CSS: VTS key initialized" );
+ p_dvd->p_css->i_title =
+ p_dvd->ifo.vmg.ptt_srpt.p_tts[i_title-1].i_tts_nb;
+ p_dvd->p_css->i_title_pos =
+ p_dvd->ifo.vts.i_pos +
+ p_dvd->ifo.vts.mat.i_tt_vobs_ssector * DVD_LB_SIZE;
+ CSSGetKey( p_dvd->p_css );
+ intf_WarnMsg( 2, "css info: vts key initialized" );
}
/*
* Set selected title start and size
*/
- DVDChapterSelect( p_method, 1 );
-
- /* start is : beginning of vts + offset to vobs + offset to vob x */
-
- p_method->i_start =
- lseek( p_input->i_handle, p_method->i_start, SEEK_SET );
+
+ /* title set offset */
+ p_dvd->i_title_start = p_dvd->ifo.vts.i_pos + DVD_LB_SIZE *
+ (off_t)( p_dvd->ifo.vts.mat.i_tt_vobs_ssector );
+
+ /* last video cell */
+ p_dvd->i_cell = -1;
+ p_dvd->i_prg_cell = -1 +
+ p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc.i_cell_nb;
+ DVDFindSector( p_dvd );
+
+ /* temporary hack to fix size in some dvds */
+ if( p_dvd->i_cell >= p_dvd->ifo.vts.c_adt.i_cell_nb )
+ {
+ p_dvd->i_cell = p_dvd->ifo.vts.c_adt.i_cell_nb - 1;
+ }
+
+ p_dvd->i_size = DVD_LB_SIZE *
+ (off_t)( p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector );
+
+ DVDChapterSelect( p_dvd, 1 );
+
+ p_dvd->i_size -= (off_t)( p_dvd->i_sector + 1 ) *DVD_LB_SIZE;
+
+ lseek( p_input->i_handle, p_dvd->i_start, SEEK_SET );
+
- intf_WarnMsg( 2, "DVD: vobstart at: %lld", p_method->i_start );
- intf_WarnMsg( 2, "DVD: stream size: %lld", p_method->i_size );
- intf_WarnMsg( 2, "DVD: number of chapters: %lld",
- p_method->i_chapter_nb );
+ intf_WarnMsg( 2, "dvd info: title: %d", i_title );
+ intf_WarnMsg( 2, "dvd info: vobstart at: %lld", p_dvd->i_start );
+ intf_WarnMsg( 2, "dvd info: stream size: %lld", p_dvd->i_size );
+ intf_WarnMsg( 2, "dvd info: number of chapters: %d",
+ p_dvd->ifo.vmg.ptt_srpt.p_tts[i_title-1].i_ptt_nb );
+
+/* intf_WarnMsg( 3, "last: %d index: %d", i_last_chapter, i_index );*/
+
+
+/* intf_WarnMsg( 3, "DVD: Cell: %d vob id: %d cell id: %d", i_end_cell, p_dvd->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_vob_id, p_dvd->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_cell_id );*/
/* Area definition */
- p_input->stream.p_selected_area->i_start = p_method->i_start;
- p_input->stream.p_selected_area->i_size = p_method->i_size;
- p_input->stream.p_selected_area->i_part_nb = p_method->i_chapter_nb;
+ p_input->stream.p_selected_area->i_start = p_dvd->i_start;
+ p_input->stream.p_selected_area->i_size = p_dvd->i_size;
/*
* Destroy obsolete ES by reinitializing program 0
p_es->i_stream_id = 0xe0;
p_es->i_type = MPEG2_VIDEO_ES;
input_SelectES( p_input, p_es );
- intf_WarnMsg( 1, "DVD: Video MPEG2 stream" );
+ intf_WarnMsg( 1, "dvd info: video MPEG2 stream" );
/* Audio ES, in the order they appear in .ifo */
- i_nb = p_method->ifo.vts.mat.i_audio_nb;
+ i_nb = p_dvd->ifo.vts.mat.i_audio_nb;
- i_ac3 = 0x80;
+ i_ac3 = 0x7f;
i_mpeg = 0xc0;
for( i = 1 ; i <= i_nb ; i++ )
{
#if 0
- fprintf( stderr, "Audio %d: %x %x %x %x %x %x\n", i,
- p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode,
- p_method->ifo.vts.mat.p_audio_atrt[i].i_multichannel_extension,
- p_method->ifo.vts.mat.p_audio_atrt[i].i_type,
- p_method->ifo.vts.mat.p_audio_atrt[i].i_appl_mode,
- p_method->ifo.vts.mat.p_audio_atrt[i].i_foo,
- p_method->ifo.vts.mat.p_audio_atrt[i].i_bar );
+ fprintf( stderr, "Audio %d: %x %x %x %x %x %x %x %x %x %x %x %x\n", i,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_num_channels,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_coding_mode,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_multichannel_extension,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_type,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_appl_mode,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_foo,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_bar,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_appl_mode,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_quantization,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_sample_freq,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code,
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_caption );
#endif
- switch( p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode )
+ switch( p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_coding_mode )
{
case 0x00: /* AC3 */
- i_id = ( ( 0x7f + i ) << 8 ) | 0xbd;
+ i_id = ( ( i_ac3 + i ) << 8 ) | 0xbd;
p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 );
p_es->i_stream_id = 0xbd;
p_es->i_type = AC3_AUDIO_ES;
p_es->b_audio = 1;
strcpy( p_es->psz_desc, Language( hton16(
- p_method->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) );
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) );
+
+ intf_WarnMsg( 1, "dvd info: audio stream %d %s\t(0x%x)",
+ i, p_es->psz_desc, i_id );
break;
case 0x02:
p_es->i_type = MPEG2_AUDIO_ES;
p_es->b_audio = 1;
strcpy( p_es->psz_desc, Language( hton16(
- p_method->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) );
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) );
+
+ intf_WarnMsg( 1, "dvd info: audio stream %d %s\t(0x%x)",
+ i, p_es->psz_desc, i_id );
break;
case 0x04: /* LPCM */
i_id = 0;
- intf_ErrMsg( "DVD: LPCM audio not handled yet" );
+ intf_ErrMsg( "dvd warning: LPCM audio not handled yet" );
break;
case 0x06: /* DTS */
i_id = 0;
- intf_ErrMsg( "DVD: DTS audio not handled yet" );
+ i_ac3--;
+ intf_ErrMsg( "dvd warning: DTS audio not handled yet" );
break;
default:
i_id = 0;
- intf_ErrMsg( "DVD: unkown audio" );
+ intf_ErrMsg( "dvd warning: unknown audio type %.2x",
+ p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_coding_mode );
}
- intf_WarnMsg( 1, "DVD: Audio stream %d %s\t(0x%x)",
- i, p_es->psz_desc, i_id );
}
/* Sub Picture ES */
- i_nb = p_method->ifo.vts.mat.i_subpic_nb;
+ i_nb = p_dvd->ifo.vts.mat.i_subpic_nb;
b_last = 0;
i_sub_pic = 0x20;
p_es->i_stream_id = 0xbd;
p_es->i_type = DVD_SPU_ES;
strcpy( p_es->psz_desc, Language( hton16(
- p_method->ifo.vts.mat.p_subpic_atrt[i-1].i_lang_code ) ) );
- intf_WarnMsg( 1, "DVD: SPU stream %d %s\t(0x%x)",
+ p_dvd->ifo.vts.mat.p_subpic_atrt[i-1].i_lang_code ) ) );
+ intf_WarnMsg( 1, "dvd info: spu stream %d %s\t(0x%x)",
i, p_es->psz_desc, i_id );
/* The before the last spu has a 0x0 prefix */
b_last =
- ( p_method->ifo.vts.mat.p_subpic_atrt[i].i_prefix == 0 );
+ ( p_dvd->ifo.vts.mat.p_subpic_atrt[i].i_prefix == 0 );
}
}
/* Audio: we check it is in the range and
* default it to the first if not */
- if( i_audio > p_method->ifo.vts.mat.i_audio_nb )
+ if( i_audio > p_dvd->ifo.vts.mat.i_audio_nb )
{
i_audio = 1;
}
if( p_input->stream.pp_selected_es[i_index] != p_es )
{
- input_UnSelectES( p_input,
+ input_UnselectES( p_input,
p_input->stream.pp_selected_es[i_index] );
input_SelectES( p_input, p_es );
- intf_WarnMsg( 1, "DVD: Audio %d selected -> %s (0x%x)",
+ intf_WarnMsg( 1, "dvd info: audio %d selected -> %s (0x%x)",
i_audio, p_es->psz_desc, p_es->i_id );
}
}
else
{
input_SelectES( p_input, p_es );
- intf_WarnMsg( 1, "DVD: Audio %d selected -> %s (0x%x)",
+ intf_WarnMsg( 1, "dvd info: audio %d selected -> %s (0x%x)",
i_audio, p_es->psz_desc, p_es->i_id );
}
}
if( ( i_spu >= 0 ) || ( i_title >= 0 ) )
{
- /* For spu: no one if none or a not existed one requested */
- if( ( i_spu <= p_method->ifo.vts.mat.i_subpic_nb ) && ( i_spu > 0 ) )
+ /* For spu: no one if none or a not existing one requested */
+ if( ( i_spu <= p_dvd->ifo.vts.mat.i_subpic_nb ) && ( i_spu > 0 ) )
{
input_SelectES( p_input, ( p_es = p_input->stream.pp_programs[0]->
- pp_es[ i_spu + p_method->ifo.vts.mat.i_audio_nb ] ) );
+ pp_es[ i_spu + p_dvd->ifo.vts.mat.i_audio_nb ] ) );
- intf_WarnMsg( 1, "DVD: SPU %d selected -> %s (0x%x)",
+ intf_WarnMsg( 1, "dvd info: spu %d selected -> %s (0x%x)",
i_spu, p_es->psz_desc, p_es->i_id );
}
}
if( ( i_chapter > 0 ) &&
( i_chapter <= p_input->stream.p_selected_area->i_part_nb ) )
{
- DVDChapterSelect( p_method, i_chapter );
-
- p_input->stream.p_selected_area->i_part = i_chapter;
+ DVDChapterSelect( p_dvd, i_chapter );
- DVDSeek( p_input, p_method->i_start -
- p_input->stream.p_selected_area->i_start );
+ p_input->stream.p_selected_area->i_tell = p_dvd->i_start -
+ p_input->stream.p_selected_area->i_start;
+ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
- intf_WarnMsg( 2, "DVD: Chapter %d start at: %lld", i_chapter,
+ intf_WarnMsg( 2, "dvd info: chapter %d start at: %lld", i_chapter,
p_input->stream.p_selected_area->i_tell );
}
*****************************************************************************/
static void DVDInit( input_thread_t * p_input )
{
- thread_dvd_data_t * p_method;
+ thread_dvd_data_t * p_dvd;
int i_title;
int i_chapter;
int i_audio;
int i_spu;
int i;
- if( (p_method = malloc( sizeof(thread_dvd_data_t) )) == NULL )
+ if( (p_dvd = malloc( sizeof(thread_dvd_data_t) )) == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
- p_input->p_plugin_data = (void *)p_method;
+ p_input->p_plugin_data = (void *)p_dvd;
p_input->p_method_data = NULL;
- p_method->i_fd = p_input->i_handle;
- /* FIXME: read several packets once */
- p_method->i_read_once = 1;
- p_method->b_encrypted = DVDCheckCSS( p_input );
+ p_dvd->i_fd = p_input->i_handle;
+
+ p_dvd->i_block_once = 1;
+ p_input->i_read_once = 8;
+
+ p_dvd->b_encrypted = DVDCheckCSS( p_input );
lseek( p_input->i_handle, 0, SEEK_SET );
/* Reading structures initialisation */
- input_NetlistInit( p_input, 4096, 4096, DVD_LB_SIZE,
- p_method->i_read_once );
- intf_WarnMsg( 2, "DVD: Netlist initialized" );
+ p_input->p_method_data =
+ DVDNetlistInit( 4096, 8192, 4096, DVD_LB_SIZE, p_dvd->i_block_once );
+ intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo initialisation */
- p_method->ifo = IfoInit( p_input->i_handle );
- intf_WarnMsg( 2, "Ifo: VMG initialized" );
+ p_dvd->ifo = IfoInit( p_input->i_handle );
+ intf_WarnMsg( 2, "ifo info: vmg initialized" );
/* CSS initialisation */
- if( p_method->b_encrypted )
+ if( p_dvd->b_encrypted )
{
- p_method->css = CSSInit( p_input->i_handle );
+ p_dvd->p_css = CSSInit( p_input->i_handle );
- if( ( p_input->b_error = p_method->css.b_error ) )
+ if( p_dvd->p_css == NULL )
{
- intf_ErrMsg( "CSS fatal error" );
+ intf_ErrMsg( "css error: fatal failure" );
+ p_input->b_error = 1;
return;
}
- intf_WarnMsg( 2, "CSS: initialized" );
+
+ intf_WarnMsg( 2, "css info: initialized" );
}
/* Initialize ES structures */
/* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock );
- /* FIXME: We consider here that one title is one title set
- * it is not true !!! */
-
- intf_WarnMsg( 2, "DVD: Number of titles: %d\n",
- p_method->ifo.vmg.mat.i_tts_nb );
+#define srpt p_dvd->ifo.vmg.ptt_srpt
+ intf_WarnMsg( 2, "dvd info: number of titles: %d", srpt.i_ttu_nb );
#define area p_input->stream.pp_areas
/* We start from 1 here since area 0 is reserved for video_ts.vob */
- for( i = 1 ; i <= p_method->ifo.vmg.mat.i_tts_nb ; i++ )
+ for( i = 1 ; i <= srpt.i_ttu_nb ; i++ )
{
input_AddArea( p_input );
area[i]->i_size = 0;
/* Number of chapter */
- area[i]->i_part_nb = 0;
+ area[i]->i_part_nb = srpt.p_tts[i-1].i_ptt_nb;
area[i]->i_part = 1;
+
/* Offset to vts_i_0.ifo */
- area[i]->i_plugin_data = p_method->ifo.i_off +
- ( p_method->ifo.vmg.ptt_srpt.p_tts[i-1].i_ssector * DVD_LB_SIZE );
+ area[i]->i_plugin_data = p_dvd->ifo.i_off +
+ ( srpt.p_tts[i-1].i_ssector * DVD_LB_SIZE );
}
#undef area
vlc_mutex_unlock( &p_input->stream.stream_lock );
/* Get requested title - if none try to find one where is the movie */
- i_title = main_GetIntVariable( INPUT_TITLE_VAR,
- p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb );
- if( i_title <= 0 || i_title >= p_method->ifo.vmg.mat.i_tts_nb )
+ i_title = main_GetIntVariable( INPUT_TITLE_VAR, 1 );
+ if( i_title <= 0 || i_title > srpt.i_ttu_nb )
{
- i_title = p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb;
+ i_title = 1;
}
+#undef srpt
/* Get requested chapter - if none defaults to first one */
i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 );
*****************************************************************************/
static void DVDEnd( input_thread_t * p_input )
{
- /* FIXME: check order of calls */
-// CSSEnd( p_input );
-// IfoEnd( (ifo_t*)(&p_input->p_plugin_data->ifo ) );
- free( p_input->stream.p_demux_data );
- free( p_input->p_plugin_data );
- input_NetlistEnd( p_input );
+ thread_dvd_data_t * p_dvd;
+ dvd_netlist_t * p_netlist;
+
+ p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data;
+ p_netlist = (dvd_netlist_t *)p_input->p_method_data;
+
+ CSSEnd( p_dvd->p_css );
+// IfoEnd( p_dvd->p_ifo ) );
+ free( p_dvd );
+ DVDNetlistEnd( p_netlist );
}
/*****************************************************************************
* EOF.
*****************************************************************************/
static int DVDRead( input_thread_t * p_input,
- data_packet_t ** pp_packets )
+ data_packet_t ** pp_packets )
{
- byte_t p_header[6];
- data_packet_t * p_data;
- size_t i_packet_size;
- int i_packet, i_error;
- thread_dvd_data_t * p_method;
+ thread_dvd_data_t * p_dvd;
+ dvd_netlist_t * p_netlist;
+ pgc_t * p_pgc;
+ struct iovec * p_vec;
+ struct data_packet_s * pp_data[p_input->i_read_once];
+ u8 * pi_cur;
+ int i_packet_size;
+ int i_iovec;
+ int i_packet;
+ int i_pos;
+ int i_read_bytes;
+ int i_read_blocks;
+ int i_chapter;
+ off_t i_off;
+ boolean_t b_eof;
+
+ p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
+ p_netlist = (dvd_netlist_t *)p_input->p_method_data;
+ p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc;
+
+ /* Get an iovec pointer */
+ if( ( p_vec = DVDGetiovec( p_netlist ) ) == NULL )
+ {
+ intf_ErrMsg( "DVD: read error" );
+ return -1;
+ }
+
+ /* Get the position of the next cell if we're at cell end */
+
+ if( p_dvd->i_sector > p_dvd->i_end_sector )
+ {
+ /* Find cell index in adress map */
+ if( DVDFindSector( p_dvd ) < 0 )
+ {
+ pp_packets[0] = NULL;
+ return 1;
+ }
+
+ /* Position the fd pointer on the right address */
+ i_off = lseek( p_dvd->i_fd,
+ p_dvd->i_title_start +
+ (off_t)( p_dvd->i_sector ) *DVD_LB_SIZE,
+ SEEK_SET );
+
+ i_chapter = 0;
- p_method = (thread_dvd_data_t *)p_input->p_plugin_data;
+ /* update chapter */
+ while( p_pgc->prg_map.pi_entry_cell[i_chapter-1] - 1 <
+ p_dvd->i_prg_cell )
+ {
+ i_chapter++;
+ }
+
+ p_dvd->i_chapter = i_chapter;
- memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
- for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.p_selected_area->i_tell = i_off -
+ p_input->stream.p_selected_area->i_start;
+ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ }
+
+ /* Reads from DVD */
+ i_read_bytes = readv( p_dvd->i_fd, p_vec, p_dvd->i_block_once );
+ i_read_blocks = ( i_read_bytes + 0x7ff ) >> 11;
+
+ /* Update netlist indexes */
+ DVDMviovec( p_netlist, i_read_blocks, pp_data );
+
+ /* Update global position */
+ p_dvd->i_sector += i_read_blocks;
+
+ i_packet = 0;
+
+ /* Read headers to compute payload length */
+ for( i_iovec = 0 ; i_iovec < i_read_blocks ; i_iovec++ )
{
- /* Read what we believe to be a packet header. */
- if( (i_error = SafeRead( p_input, p_header, 6 )) )
+ if( p_dvd->b_encrypted )
{
- return( i_error );
+ CSSDescrambleSector( p_dvd->p_css->pi_title_key,
+ p_vec[i_iovec].iov_base );
+ ((u8*)(p_vec[i_iovec].iov_base))[0x14] &= 0x8F;
}
- if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
+ i_pos = 0;
+
+ while( i_pos < p_netlist->i_buffer_size )
{
- /* This is not the startcode of a packet. Read the stream
- * until we find one. */
- u32 i_startcode = U32_AT(p_header);
- int i_nb;
- byte_t i_dummy;
+ pi_cur = (u8*)(p_vec[i_iovec].iov_base + i_pos);
- if( i_startcode )
+ /*default header */
+ if( U32_AT( pi_cur ) != 0x1BA )
{
- /* It is common for MPEG-1 streams to pad with zeros
- * (although it is forbidden by the recommendation), so
- * don't bother everybody in this case. */
- intf_WarnMsg( 1, "Garbage at input (%x)", i_startcode );
+ /* That's the case for all packets, except pack header. */
+ i_packet_size = U16_AT( pi_cur + 4 );
+ pp_packets[i_packet] = DVDNewPtr( p_netlist );
}
-
- while( (i_startcode & 0xFFFFFF00) != 0x100L )
+ else
{
- i_startcode <<= 8;
- if( (i_nb = SafeRead( p_input, &i_dummy, 1 )) != 0 )
+ /* Pack header. */
+ if( ( pi_cur[4] & 0xC0 ) == 0x40 )
{
- i_startcode |= i_dummy;
+ /* MPEG-2 */
+ i_packet_size = 8;
+ }
+ else if( ( pi_cur[4] & 0xF0 ) == 0x20 )
+ {
+ /* MPEG-1 */
+ i_packet_size = 6;
}
else
{
- return( 1 );
+ intf_ErrMsg( "Unable to determine stream type" );
+ return( -1 );
}
- }
- /* Packet found. */
- *(u32 *)p_header = U32_AT(&i_startcode);
- if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
- {
- return( i_error );
- }
- }
+ pp_packets[i_packet] = pp_data[i_iovec];
- if( U32_AT(p_header) != 0x1BA )
- {
- /* That's the case for all packets, except pack header. */
- i_packet_size = U16_AT(&p_header[4]);
- }
- else
- {
- /* Pack header. */
- if( (p_header[4] & 0xC0) == 0x40 )
- {
- /* MPEG-2 */
- i_packet_size = 8;
- }
- else if( (p_header[4] & 0xF0) == 0x20 )
- {
- /* MPEG-1 */
- i_packet_size = 6;
}
- else
- {
- intf_ErrMsg( "Unable to determine stream type" );
- return( -1 );
- }
- }
- /* Fetch a packet of the appropriate size. */
- if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
- {
- intf_ErrMsg( "Out of memory" );
- return( -1 );
- }
+ (*pp_data[i_iovec]->pi_refcount)++;
- /* Copy the header we already read. */
- memcpy( p_data->p_buffer, p_header, 6 );
+ pp_packets[i_packet]->pi_refcount = pp_data[i_iovec]->pi_refcount;
- /* Read the remaining of the packet. */
- if( i_packet_size && (i_error =
- SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
- {
- return( i_error );
- }
+ pp_packets[i_packet]->p_buffer = pp_data[i_iovec]->p_buffer;
- /* In MPEG-2 pack headers we still have to read stuffing bytes. */
- if( U32_AT(p_header) == 0x1BA )
- {
- if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
- {
- /* MPEG-2 stuffing bytes */
- byte_t p_garbage[8];
- if( (i_error = SafeRead( p_input, p_garbage,
- p_data->p_buffer[13] & 0x7)) )
- {
- return( i_error );
- }
- }
- }
+ pp_packets[i_packet]->p_payload_start =
+ pp_packets[i_packet]->p_buffer + i_pos;
- /* Give the packet to the other input stages. */
- pp_packets[i_packet] = p_data;
+ pp_packets[i_packet]->p_payload_end =
+ pp_packets[i_packet]->p_payload_start + i_packet_size + 6;
+
+ i_packet++;
+ i_pos += i_packet_size + 6;
+ }
}
- return( 0 );
+ pp_packets[i_packet] = NULL;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.p_selected_area->i_tell +=
+ p_dvd->i_block_once *DVD_LB_SIZE;
+ b_eof = p_input->stream.p_selected_area->i_tell < p_dvd->i_size ? 0 : 1;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ if( ( i_read_blocks == p_dvd->i_block_once ) && ( !b_eof ) )
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
}
* DVDSeek : Goes to a given position on the stream ; this one is used by the
* input and translate chronological position from input to logical postion
* on the device
+ * ---
+ * The lock should be taken before calling this function.
*****************************************************************************/
static void DVDSeek( input_thread_t * p_input, off_t i_off )
{
- thread_dvd_data_t * p_method;
+ thread_dvd_data_t * p_dvd;
+ pgc_t * p_pgc;
off_t i_pos;
+ int i_prg_cell;
+ int i_cell;
+ int i_chapter;
- p_method = ( thread_dvd_data_t * )p_input->p_plugin_data;
+ p_dvd = ( thread_dvd_data_t * )p_input->p_plugin_data;
+ p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc;
+
+ /* update navigation data */
+ p_dvd->i_sector = i_off >> 11;
+
+ i_prg_cell = 0;
+ i_cell = 0;
+ i_chapter = 1;
+
+ /* parse vobu address map to find program cell */
+ while( p_pgc->p_cell_play_inf[i_prg_cell].i_lsector < p_dvd->i_sector )
+ {
+ i_prg_cell++;
+ }
+ /* parse cell address map to find cell */
+ while( p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_esector <=
+ p_dvd->i_sector + 1 )
+ {
+ i_cell++;
+ }
+
+ p_dvd->i_prg_cell = i_prg_cell;
+ p_dvd->i_cell = i_cell - 1; /* DVDFindSector will add one */
+
+ /* check coherence of data */
+ DVDFindSector( p_dvd );
+
+ /* update chapter */
+ while( p_pgc->prg_map.pi_entry_cell[i_chapter-1] - 1 < p_dvd->i_prg_cell )
+ {
+ i_chapter++;
+ }
+
+ p_dvd->i_chapter = i_chapter;
- /* We have to take care of offset of beginning of title */
+ /* we have to take care of offset of beginning of title */
i_pos = i_off + p_input->stream.p_selected_area->i_start;
- /* With DVD, we have to be on a sector boundary */
+ /* with DVD, we have to be on a sector boundary */
i_pos = i_pos & (~0x7ff);
- i_pos = lseek( p_input->i_handle, i_pos, SEEK_SET );
+ i_pos = lseek( p_dvd->i_fd, i_pos, SEEK_SET );
p_input->stream.p_selected_area->i_tell = i_pos -
p_input->stream.p_selected_area->i_start;
+ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
return;
}