Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

dvdread.c

00001 /*****************************************************************************
00002  * dvdread.c : DvdRead input module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2001-2004 the VideoLAN team
00005  * $Id: dvdread.c 12862 2005-10-16 20:08:22Z jpsaman $
00006  *
00007  * Authors: St�hane Borel <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <stdio.h>
00029 #include <stdlib.h>                                      /* malloc(), free() */
00030 #include <string.h>                                              /* strdup() */
00031 
00032 #include <vlc/vlc.h>
00033 #include <vlc/input.h>
00034 
00035 #include "iso_lang.h"
00036 
00037 #include "../demux/ps.h"
00038 
00039 #ifdef HAVE_UNISTD_H
00040 #   include <unistd.h>
00041 #endif
00042 
00043 #include <fcntl.h>
00044 #include <sys/types.h>
00045 #include <sys/stat.h>
00046 #include <string.h>
00047 
00048 #include <dvdread/dvd_reader.h>
00049 #include <dvdread/ifo_types.h>
00050 #include <dvdread/ifo_read.h>
00051 #include <dvdread/nav_read.h>
00052 #include <dvdread/nav_print.h>
00053 
00054 /*****************************************************************************
00055  * Module descriptor
00056  *****************************************************************************/
00057 #define ANGLE_TEXT N_("DVD angle")
00058 #define ANGLE_LONGTEXT N_( \
00059     "Allows you to select the default DVD angle." )
00060 
00061 #define CACHING_TEXT N_("Caching value in ms")
00062 #define CACHING_LONGTEXT N_( \
00063     "Allows you to modify the default caching value for DVDread streams. " \
00064     "This value should be set in millisecond units." )
00065 
00066 #define CSSMETHOD_TEXT N_("Method used by libdvdcss for decryption")
00067 #define CSSMETHOD_LONGTEXT N_( \
00068     "Set the method used by libdvdcss for key decryption.\n" \
00069     "title: decrypted title key is guessed from the encrypted sectors of " \
00070            "the stream. Thus it should work with a file as well as the " \
00071            "DVD device. But it sometimes takes much time to decrypt a title " \
00072            "key and may even fail. With this method, the key is only checked "\
00073            "at the beginning of each title, so it won't work if the key " \
00074            "changes in the middle of a title.\n" \
00075     "disc: the disc key is first cracked, then all title keys can be " \
00076            "decrypted instantly, which allows us to check them often.\n" \
00077     "key: the same as \"disc\" if you don't have a file with player keys " \
00078            "at compilation time. If you do, the decryption of the disc key " \
00079            "will be faster with this method. It is the one that was used by " \
00080            "libcss.\n" \
00081     "The default method is: key.")
00082 
00083 static char *psz_css_list[] = { "title", "disc", "key" };
00084 static char *psz_css_list_text[] = { N_("title"), N_("Disc"), N_("Key") };
00085 
00086 static int  Open ( vlc_object_t * );
00087 static void Close( vlc_object_t * );
00088 
00089 vlc_module_begin();
00090     set_shortname( _("DVD without menus") );
00091     set_description( _("DVDRead Input (DVD without menu support)") );
00092     set_category( CAT_INPUT );
00093     set_subcategory( SUBCAT_INPUT_ACCESS );
00094     add_integer( "dvdread-angle", 1, NULL, ANGLE_TEXT,
00095         ANGLE_LONGTEXT, VLC_FALSE );
00096     add_integer( "dvdread-caching", DEFAULT_PTS_DELAY / 1000, NULL,
00097         CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
00098     add_string( "dvdread-css-method", NULL, NULL, CSSMETHOD_TEXT,
00099                 CSSMETHOD_LONGTEXT, VLC_TRUE );
00100         change_string_list( psz_css_list, psz_css_list_text, 0 );
00101     set_capability( "access_demux", 0 );
00102     add_shortcut( "dvd" );
00103     add_shortcut( "dvdread" );
00104     add_shortcut( "dvdsimple" );
00105     set_callbacks( Open, Close );
00106 vlc_module_end();
00107 
00108 /* how many blocks DVDRead will read in each loop */
00109 #define DVD_BLOCK_READ_ONCE 4
00110 
00111 /*****************************************************************************
00112  * Local prototypes
00113  *****************************************************************************/
00114 
00115 struct demux_sys_t
00116 {
00117     /* DVDRead state */
00118     dvd_reader_t *p_dvdread;
00119     dvd_file_t   *p_title;
00120 
00121     ifo_handle_t *p_vmg_file;
00122     ifo_handle_t *p_vts_file;
00123 
00124     int i_title;
00125     int i_chapter, i_chapters;
00126     int i_angle, i_angles;
00127 
00128     tt_srpt_t    *p_tt_srpt;
00129     pgc_t        *p_cur_pgc;
00130     dsi_t        dsi_pack;
00131     int          i_ttn;
00132 
00133     int i_pack_len;
00134     int i_cur_block;
00135     int i_next_vobu;
00136 
00137     int i_mux_rate;
00138 
00139     /* Current title start/end blocks */
00140     int i_title_start_block;
00141     int i_title_end_block;
00142     int i_title_blocks;
00143     int i_title_offset;
00144     mtime_t i_title_cur_time;
00145 
00146     int i_title_start_cell;
00147     int i_title_end_cell;
00148     int i_cur_cell;
00149     int i_next_cell;
00150     mtime_t i_cell_cur_time;
00151     mtime_t i_cell_duration;
00152 
00153     /* Track */
00154     ps_track_t    tk[PS_TK_COUNT];
00155 
00156     int           i_titles;
00157     input_title_t **titles;
00158 
00159     /* Video */
00160     int i_aspect;
00161 
00162     /* SPU */
00163     uint32_t clut[16];
00164 };
00165 
00166 static int Control   ( demux_t *, int, va_list );
00167 static int Demux     ( demux_t * );
00168 static int DemuxBlock( demux_t *, uint8_t *, int );
00169 
00170 static void DemuxTitles( demux_t *, int * );
00171 static void ESNew( demux_t *, int, int );
00172 
00173 static int  DvdReadSetArea  ( demux_t *, int, int, int );
00174 static void DvdReadSeek     ( demux_t *, int );
00175 static void DvdReadHandleDSI( demux_t *, uint8_t * );
00176 static void DvdReadFindCell ( demux_t * );
00177 
00178 /*****************************************************************************
00179  * Open:
00180  *****************************************************************************/
00181 static int Open( vlc_object_t *p_this )
00182 {
00183     demux_t      *p_demux = (demux_t*)p_this;
00184     demux_sys_t  *p_sys;
00185     char         *psz_name;
00186     char         *psz_dvdcss_env;
00187     dvd_reader_t *p_dvdread;
00188     ifo_handle_t *p_vmg_file;
00189     vlc_value_t  val;
00190 
00191     if( !p_demux->psz_path || !*p_demux->psz_path )
00192     {
00193         /* Only when selected */
00194         if( !p_this->b_force ) return VLC_EGENERIC;
00195 
00196         psz_name = var_CreateGetString( p_this, "dvd" );
00197         if( !psz_name )
00198         {
00199             psz_name = strdup("");
00200         }
00201     }
00202     else
00203         psz_name = strdup( p_demux->psz_path );
00204 
00205 #ifdef WIN32
00206     if( psz_name[0] && psz_name[1] == ':' &&
00207         psz_name[2] == '\\' && psz_name[3] == '\0' ) psz_name[2] = '\0';
00208 #endif
00209 
00210     /* Override environment variable DVDCSS_METHOD with config option
00211      * (FIXME: this creates a small memory leak) */
00212     psz_dvdcss_env = config_GetPsz( p_demux, "dvdread-css-method" );
00213     if( psz_dvdcss_env && *psz_dvdcss_env )
00214     {
00215         char *psz_env;
00216 
00217         psz_env = malloc( strlen("DVDCSS_METHOD=") +
00218                           strlen( psz_dvdcss_env ) + 1 );
00219         if( !psz_env )
00220         {
00221             free( psz_dvdcss_env );
00222             return VLC_ENOMEM;
00223         }
00224 
00225         sprintf( psz_env, "%s%s", "DVDCSS_METHOD=", psz_dvdcss_env );
00226 
00227         putenv( psz_env );
00228     }
00229     if( psz_dvdcss_env ) free( psz_dvdcss_env );
00230 
00231     /* Open dvdread */
00232     if( !(p_dvdread = DVDOpen( psz_name )) )
00233     {
00234         msg_Err( p_demux, "DVDRead cannot open source: %s", psz_name );
00235         free( psz_name );
00236         return VLC_EGENERIC;
00237     }
00238     free( psz_name );
00239 
00240     /* Ifo allocation & initialisation */
00241     if( !( p_vmg_file = ifoOpen( p_dvdread, 0 ) ) )
00242     {
00243         msg_Warn( p_demux, "cannot open VMG info" );
00244         return VLC_EGENERIC;
00245     }
00246     msg_Dbg( p_demux, "VMG opened" );
00247 
00248     /* Fill p_demux field */
00249     p_demux->pf_demux = Demux;
00250     p_demux->pf_control = Control;
00251     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00252     memset( p_sys, 0, sizeof( demux_sys_t ) );
00253 
00254     ps_track_init( p_sys->tk );
00255     p_sys->i_aspect = -1;
00256     p_sys->i_title_cur_time = (mtime_t) 0;
00257     p_sys->i_cell_cur_time = (mtime_t) 0;
00258     p_sys->i_cell_duration = (mtime_t) 0;
00259 
00260     p_sys->p_dvdread = p_dvdread;
00261     p_sys->p_vmg_file = p_vmg_file;
00262     p_sys->p_title = NULL;
00263     p_sys->p_vts_file = NULL;
00264 
00265     p_sys->i_title = p_sys->i_chapter = -1;
00266     p_sys->i_mux_rate = 0;
00267 
00268     var_Create( p_demux, "dvdread-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
00269     var_Get( p_demux, "dvdread-angle", &val );
00270     p_sys->i_angle = val.i_int > 0 ? val.i_int : 1;
00271 
00272     DemuxTitles( p_demux, &p_sys->i_angle );
00273     if( DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle ) != VLC_SUCCESS )
00274     {
00275         Close( p_this );
00276         msg_Err( p_demux, "DvdReadSetArea(0,0,%i) failed (can't decrypt DVD?)",
00277                  p_sys->i_angle );
00278         return VLC_EGENERIC;
00279     }
00280 
00281     /* Update default_pts to a suitable value for dvdread access */
00282     var_Create( p_demux, "dvdread-caching",
00283                 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
00284 
00285     return VLC_SUCCESS;
00286 }
00287 
00288 /*****************************************************************************
00289  * Close:
00290  *****************************************************************************/
00291 static void Close( vlc_object_t *p_this )
00292 {
00293     demux_t     *p_demux = (demux_t*)p_this;
00294     demux_sys_t *p_sys = p_demux->p_sys;
00295     int i;
00296 
00297     for( i = 0; i < PS_TK_COUNT; i++ )
00298     {
00299         ps_track_t *tk = &p_sys->tk[i];
00300         if( tk->b_seen )
00301         {
00302             es_format_Clean( &tk->fmt );
00303             if( tk->es ) es_out_Del( p_demux->out, tk->es );
00304         }
00305     }
00306 
00307     /* Close libdvdread */
00308     if( p_sys->p_title ) DVDCloseFile( p_sys->p_title );
00309     if( p_sys->p_vts_file ) ifoClose( p_sys->p_vts_file );
00310     if( p_sys->p_vmg_file ) ifoClose( p_sys->p_vmg_file );
00311     DVDClose( p_sys->p_dvdread );
00312 
00313     free( p_sys );
00314 }
00315 
00316 static int64_t dvdtime_to_time( dvd_time_t *dtime, uint8_t still_time )
00317 {
00318 /* Macro to convert Binary Coded Decimal to Decimal */
00319 #define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))
00320 
00321     double f_fps, f_ms;
00322     int64_t i_micro_second = 0;
00323 
00324     if (still_time == 0 || still_time == 0xFF)
00325     {
00326         i_micro_second += (int64_t)(BCD2D(dtime->hour)) * 60 * 60 * 1000000;
00327         i_micro_second += (int64_t)(BCD2D(dtime->minute)) * 60 * 1000000;
00328         i_micro_second += (int64_t)(BCD2D(dtime->second)) * 1000000;
00329 
00330         switch((dtime->frame_u & 0xc0) >> 6) 
00331         {
00332         case 1:
00333             f_fps = 25.0;
00334             break;
00335         case 3:
00336             f_fps = 29.97;
00337             break;
00338         default:
00339             f_fps = 2500.0;
00340             break;
00341         }
00342         f_ms = BCD2D(dtime->frame_u&0x3f) * 1000.0 / f_fps;
00343         i_micro_second += (int64_t)(f_ms * 1000.0);
00344     }
00345     else
00346     {
00347         i_micro_second = still_time;
00348         i_micro_second = (int64_t)((double)i_micro_second * 1000000.0);
00349     }
00350 
00351     return i_micro_second;
00352 }
00353 
00354 /*****************************************************************************
00355  * Control:
00356  *****************************************************************************/
00357 static int Control( demux_t *p_demux, int i_query, va_list args )
00358 {
00359     demux_sys_t *p_sys = p_demux->p_sys;
00360     double f, *pf;
00361     vlc_bool_t *pb;
00362     int64_t *pi64;
00363     input_title_t ***ppp_title;
00364     int *pi_int;
00365     int i;
00366 
00367     switch( i_query )
00368     {
00369         case DEMUX_GET_POSITION:
00370         {
00371             pf = (double*) va_arg( args, double* );
00372 
00373             if( p_sys->i_title_blocks > 0 )
00374                 *pf = (double)p_sys->i_title_offset / p_sys->i_title_blocks;
00375             else
00376                 *pf = 0.0;
00377 
00378             return VLC_SUCCESS;
00379         }
00380         case DEMUX_SET_POSITION:
00381         {
00382             f = (double)va_arg( args, double );
00383 
00384             DvdReadSeek( p_demux, f * p_sys->i_title_blocks );
00385 
00386             return VLC_SUCCESS;
00387         }
00388         case DEMUX_GET_TIME:
00389             pi64 = (int64_t*)va_arg( args, int64_t * );
00390             if( p_sys->i_mux_rate > 0 )
00391             {
00392                 *pi64 = (int64_t)1000000 * DVD_VIDEO_LB_LEN *
00393                         p_sys->i_title_offset / 50 / p_sys->i_mux_rate;
00394                 return VLC_SUCCESS;
00395             }
00396             *pi64 = 0;
00397             return VLC_EGENERIC;
00398 
00399         case DEMUX_GET_LENGTH:
00400             pi64 = (int64_t*)va_arg( args, int64_t * );
00401             if( p_sys->i_mux_rate > 0 )
00402             {
00403                 *pi64 = (int64_t)1000000 * DVD_VIDEO_LB_LEN *
00404                         p_sys->i_title_blocks / 50 / p_sys->i_mux_rate;
00405                 return VLC_SUCCESS;
00406             }
00407             *pi64 = 0;
00408             return VLC_EGENERIC;
00409 
00410         /* Special for access_demux */
00411         case DEMUX_CAN_PAUSE:
00412         case DEMUX_CAN_CONTROL_PACE:
00413             /* TODO */
00414             pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
00415             *pb = VLC_TRUE;
00416             return VLC_SUCCESS;
00417 
00418         case DEMUX_SET_PAUSE_STATE:
00419             return VLC_SUCCESS;
00420 
00421         case DEMUX_GET_TITLE_INFO:
00422             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
00423             pi_int    = (int*)va_arg( args, int* );
00424             *((int*)va_arg( args, int* )) = 1; /* Title offset */
00425             *((int*)va_arg( args, int* )) = 1; /* Chapter offset */
00426 
00427             /* Duplicate title infos */
00428             *pi_int = p_sys->i_titles;
00429             *ppp_title = malloc( sizeof(input_title_t **) * p_sys->i_titles );
00430             for( i = 0; i < p_sys->i_titles; i++ )
00431             {
00432                 (*ppp_title)[i] = vlc_input_title_Duplicate(p_sys->titles[i]);
00433             }
00434             return VLC_SUCCESS;
00435 
00436         case DEMUX_SET_TITLE:
00437             i = (int)va_arg( args, int );
00438             if( DvdReadSetArea( p_demux, i, 0, -1 ) != VLC_SUCCESS )
00439             {
00440                 msg_Warn( p_demux, "cannot set title/chapter" );
00441                 return VLC_EGENERIC;
00442             }
00443             p_demux->info.i_update |=
00444                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
00445             p_demux->info.i_title = i;
00446             p_demux->info.i_seekpoint = 0;
00447             return VLC_SUCCESS;
00448 
00449         case DEMUX_SET_SEEKPOINT:
00450             i = (int)va_arg( args, int );
00451             if( DvdReadSetArea( p_demux, -1, i, -1 ) != VLC_SUCCESS )
00452             {
00453                 msg_Warn( p_demux, "cannot set title/chapter" );
00454                 return VLC_EGENERIC;
00455             }
00456             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
00457             p_demux->info.i_seekpoint = i;
00458             return VLC_SUCCESS;
00459 
00460         case DEMUX_GET_PTS_DELAY:
00461             pi64 = (int64_t*)va_arg( args, int64_t * );
00462             *pi64 = (int64_t)var_GetInteger( p_demux, "dvdread-caching" )*1000;
00463             return VLC_SUCCESS;
00464 
00465         /* TODO implement others */
00466         default:
00467             return VLC_EGENERIC;
00468     }
00469 }
00470 
00471 /*****************************************************************************
00472  * Demux:
00473  *****************************************************************************/
00474 static int Demux( demux_t *p_demux )
00475 {
00476     demux_sys_t *p_sys = p_demux->p_sys;
00477 
00478     uint8_t p_buffer[DVD_VIDEO_LB_LEN * DVD_BLOCK_READ_ONCE];
00479     int i_blocks_once, i_read;
00480     int i;
00481 
00482     /*
00483      * Playback by cell in this pgc, starting at the cell for our chapter.
00484      */
00485 
00486     /*
00487      * Check end of pack, and select the following one
00488      */
00489     if( !p_sys->i_pack_len )
00490     {
00491         /* Read NAV packet */
00492         if( DVDReadBlocks( p_sys->p_title, p_sys->i_next_vobu,
00493                            1, p_buffer ) != 1 )
00494         {
00495             msg_Err( p_demux, "read failed for block %d", p_sys->i_next_vobu );
00496             return -1;
00497         }
00498 
00499         /* Basic check to be sure we don't have a empty title
00500          * go to next title if so */
00501         //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
00502 
00503         /* Parse the contained dsi packet */
00504         DvdReadHandleDSI( p_demux, p_buffer );
00505 
00506         /* End of title */
00507         if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells )
00508         {
00509             if( p_sys->i_title + 1 >= p_sys->i_titles )
00510             {
00511                 return 0; /* EOF */
00512             }
00513 
00514             DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
00515         }
00516 
00517         if( p_sys->i_pack_len >= 1024 )
00518         {
00519             msg_Err( p_demux, "i_pack_len >= 1024 (%i). "
00520                      "This shouldn't happen!", p_sys->i_pack_len );
00521             return 0; /* EOF */
00522         }
00523 
00524         /* FIXME: Ugly kludge: we send the pack block to the input for it
00525          * sometimes has a zero scr and restart the sync */
00526         p_sys->i_cur_block++;
00527         p_sys->i_title_offset++;
00528 
00529         DemuxBlock( p_demux, p_buffer, DVD_VIDEO_LB_LEN );
00530     }
00531 
00532     if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells )
00533     {
00534         if( p_sys->i_title + 1 >= p_sys->i_titles )
00535         {
00536             return 0; /* EOF */
00537         }
00538 
00539         DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
00540     }
00541 
00542     /*
00543      * Read actual data
00544      */
00545     i_blocks_once = __MIN( p_sys->i_pack_len, DVD_BLOCK_READ_ONCE );
00546     p_sys->i_pack_len -= i_blocks_once;
00547 
00548     /* Reads from DVD */
00549     i_read = DVDReadBlocks( p_sys->p_title, p_sys->i_cur_block,
00550                             i_blocks_once, p_buffer );
00551     if( i_read != i_blocks_once )
00552     {
00553         msg_Err( p_demux, "read failed for %d/%d blocks at 0x%02x",
00554                  i_read, i_blocks_once, p_sys->i_cur_block );
00555         return -1;
00556     }
00557 
00558     p_sys->i_cur_block += i_read;
00559     p_sys->i_title_offset += i_read;
00560 
00561 #if 0
00562     msg_Dbg( p_demux, "i_blocks: %d len: %d current: 0x%02x",
00563              i_read, p_sys->i_pack_len, p_sys->i_cur_block );
00564 #endif
00565 
00566     for( i = 0; i < i_read; i++ )
00567     {
00568         DemuxBlock( p_demux, p_buffer + i * DVD_VIDEO_LB_LEN,
00569                     DVD_VIDEO_LB_LEN );
00570     }
00571 
00572 #undef p_pgc
00573 
00574     return 1;
00575 }
00576 
00577 /*****************************************************************************
00578  * DemuxBlock: demux a given block
00579  *****************************************************************************/
00580 static int DemuxBlock( demux_t *p_demux, uint8_t *pkt, int i_pkt )
00581 {
00582     demux_sys_t *p_sys = p_demux->p_sys;
00583     uint8_t     *p = pkt;
00584 
00585     while( p < &pkt[i_pkt] )
00586     {
00587         int i_size = ps_pkt_size( p, &pkt[i_pkt] - p );
00588         block_t *p_pkt;
00589         if( i_size <= 0 )
00590         {
00591             break;
00592         }
00593 
00594         /* Create a block */
00595         p_pkt = block_New( p_demux, i_size );
00596         memcpy( p_pkt->p_buffer, p, i_size);
00597 
00598         /* Parse it and send it */
00599         switch( 0x100 | p[3] )
00600         {
00601         case 0x1b9:
00602         case 0x1bb:
00603         case 0x1bc:
00604 
00605 #ifdef DVDREAD_DEBUG
00606             if( p[3] == 0xbc )
00607             {
00608                 msg_Warn( p_demux, "received a PSM packet" );
00609             }
00610             else if( p[3] == 0xbb )
00611             {
00612                 msg_Warn( p_demux, "received a SYSTEM packet" );
00613             }
00614 #endif
00615             block_Release( p_pkt );
00616             break;
00617 
00618         case 0x1ba:
00619         {
00620             int64_t i_scr;
00621             int i_mux_rate;
00622             if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) )
00623             {
00624                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr );
00625                 if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
00626             }
00627             block_Release( p_pkt );
00628             break;
00629         }
00630         default:
00631         {
00632             int i_id = ps_pkt_id( p_pkt );
00633             if( i_id >= 0xc0 )
00634             {
00635                 ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
00636 
00637                 if( !tk->b_seen )
00638                 {
00639                     ESNew( p_demux, i_id, 0 );
00640                 }
00641                 if( tk->b_seen && tk->es &&
00642                     !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
00643                 {
00644                     es_out_Send( p_demux->out, tk->es, p_pkt );
00645                 }
00646                 else
00647                 {
00648                     block_Release( p_pkt );
00649                 }
00650             }
00651             else
00652             {
00653                 block_Release( p_pkt );
00654             }
00655             break;
00656         }
00657         }
00658 
00659         p += i_size;
00660     }
00661 
00662     return VLC_SUCCESS;
00663 }
00664 
00665 /*****************************************************************************
00666  * ESNew: register a new elementary stream
00667  *****************************************************************************/
00668 static void ESNew( demux_t *p_demux, int i_id, int i_lang )
00669 {
00670     demux_sys_t *p_sys = p_demux->p_sys;
00671     ps_track_t  *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
00672     char psz_language[3];
00673 
00674     if( tk->b_seen ) return;
00675 
00676     if( ps_track_fill( tk, 0, i_id ) )
00677     {
00678         msg_Warn( p_demux, "unknown codec for id=0x%x", i_id );
00679         return;
00680     }
00681 
00682     psz_language[0] = psz_language[1] = psz_language[2] = 0;
00683     if( i_lang && i_lang != 0xffff )
00684     {
00685         psz_language[0] = (i_lang >> 8)&0xff;
00686         psz_language[1] = (i_lang     )&0xff;
00687     }
00688 
00689     /* Add a new ES */
00690     if( tk->fmt.i_cat == VIDEO_ES )
00691     {
00692         if( p_sys->i_aspect >= 0 )
00693         {
00694             tk->fmt.video.i_aspect = p_sys->i_aspect;
00695         }
00696     }
00697     else if( tk->fmt.i_cat == AUDIO_ES )
00698     {
00699         int i_audio = -1;
00700         /* find the audio number PLEASE find another way */
00701         if( (i_id&0xbdf8) == 0xbd88 )       /* dts */
00702         {
00703             i_audio = i_id&0x07;
00704         }
00705         else if( (i_id&0xbdf0) == 0xbd80 )  /* a52 */
00706         {
00707             i_audio = i_id&0xf;
00708         }
00709         else if( (i_id&0xbdf0) == 0xbda0 )  /* lpcm */
00710         {
00711             i_audio = i_id&0x1f;
00712         }
00713         else if( ( i_id&0xe0 ) == 0xc0 )    /* mpga */
00714         {
00715             i_audio = i_id&0x1f;
00716         }
00717 
00718         if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
00719     }
00720     else if( tk->fmt.i_cat == SPU_ES )
00721     {
00722         /* Palette */
00723         tk->fmt.subs.spu.palette[0] = 0xBeef;
00724         memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut,
00725                 16 * sizeof( uint32_t ) );
00726 
00727         if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
00728     }
00729 
00730     tk->es = es_out_Add( p_demux->out, &tk->fmt );
00731     tk->b_seen = VLC_TRUE;
00732 }
00733 
00734 /*****************************************************************************
00735  * DvdReadSetArea: initialize input data for title x, chapter y.
00736  * It should be called for each user navigation request.
00737  *****************************************************************************
00738  * Take care that i_title and i_chapter start from 0.
00739  *****************************************************************************/
00740 static int DvdReadSetArea( demux_t *p_demux, int i_title, int i_chapter,
00741                            int i_angle )
00742 {
00743     demux_sys_t *p_sys = p_demux->p_sys;
00744     int pgc_id = 0, pgn = 0;
00745     int i;
00746 
00747 #define p_pgc p_sys->p_cur_pgc
00748 #define p_vmg p_sys->p_vmg_file
00749 #define p_vts p_sys->p_vts_file
00750 
00751     if( i_title >= 0 && i_title < p_sys->i_titles &&
00752         i_title != p_sys->i_title )
00753     {
00754         int i_start_cell, i_end_cell;
00755 
00756         if( p_sys->p_title != NULL ) DVDCloseFile( p_sys->p_title );
00757         if( p_vts != NULL ) ifoClose( p_vts );
00758         p_sys->i_title = i_title;
00759 
00760         /*
00761          *  We have to load all title information
00762          */
00763         msg_Dbg( p_demux, "open VTS %d, for title %d",
00764                  p_vmg->tt_srpt->title[i_title].title_set_nr, i_title + 1 );
00765 
00766         /* Ifo vts */
00767         if( !( p_vts = ifoOpen( p_sys->p_dvdread,
00768                p_vmg->tt_srpt->title[i_title].title_set_nr ) ) )
00769         {
00770             msg_Err( p_demux, "fatal error in vts ifo" );
00771             return VLC_EGENERIC;
00772         }
00773 
00774         /* Title position inside the selected vts */
00775         p_sys->i_ttn = p_vmg->tt_srpt->title[i_title].vts_ttn;
00776 
00777         /* Find title start/end */
00778         pgc_id = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgcn;
00779         pgn = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgn;
00780         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
00781 
00782         p_sys->i_title_start_cell =
00783             i_start_cell = p_pgc->program_map[pgn - 1] - 1;
00784         p_sys->i_title_start_block =
00785             p_pgc->cell_playback[i_start_cell].first_sector;
00786 
00787         p_sys->i_title_end_cell =
00788             i_end_cell = p_pgc->nr_of_cells - 1;
00789         p_sys->i_title_end_block =
00790             p_pgc->cell_playback[i_end_cell].last_sector;
00791 
00792         p_sys->i_title_offset = 0;
00793 
00794         p_sys->i_title_blocks = 0;
00795         for( i = i_start_cell; i <= i_end_cell; i++ )
00796         {
00797             p_sys->i_title_blocks += p_pgc->cell_playback[i].last_sector -
00798                 p_pgc->cell_playback[i].first_sector + 1;
00799         }
00800 
00801         msg_Dbg( p_demux, "title %d vts_title %d pgc %d pgn %d "
00802                  "start %d end %d blocks: %d",
00803                  i_title + 1, p_sys->i_ttn, pgc_id, pgn,
00804                  p_sys->i_title_start_block, p_sys->i_title_end_block,
00805                  p_sys->i_title_blocks );
00806 
00807         /*
00808          * Set properties for current chapter
00809          */
00810         p_sys->i_chapter = 0;
00811         p_sys->i_chapters =
00812             p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].nr_of_ptts;
00813 
00814         pgc_id = p_vts->vts_ptt_srpt->title[
00815                     p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgcn;
00816         pgn = p_vts->vts_ptt_srpt->title[
00817                     p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgn;
00818 
00819         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
00820         p_sys->i_pack_len = 0;
00821         p_sys->i_next_cell =
00822             p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
00823         DvdReadFindCell( p_demux );
00824 
00825         p_sys->i_next_vobu = p_sys->i_cur_block =
00826             p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
00827 
00828         /*
00829          * Angle management
00830          */
00831         p_sys->i_angles = p_vmg->tt_srpt->title[i_title].nr_of_angles;
00832         if( p_sys->i_angle > p_sys->i_angles ) p_sys->i_angle = 1;
00833 
00834         /*
00835          * We've got enough info, time to open the title set data.
00836          */
00837         if( !( p_sys->p_title = DVDOpenFile( p_sys->p_dvdread,
00838             p_vmg->tt_srpt->title[i_title].title_set_nr,
00839             DVD_READ_TITLE_VOBS ) ) )
00840         {
00841             msg_Err( p_demux, "cannot open title (VTS_%02d_1.VOB)",
00842                      p_vmg->tt_srpt->title[i_title].title_set_nr );
00843             return VLC_EGENERIC;
00844         }
00845 
00846         //IfoPrintTitle( p_demux );
00847 
00848         /*
00849          * Destroy obsolete ES by reinitializing program 0
00850          * and find all ES in title with ifo data
00851          */
00852         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00853 
00854         for( i = 0; i < PS_TK_COUNT; i++ )
00855         {
00856             ps_track_t *tk = &p_sys->tk[i];
00857             if( tk->b_seen )
00858             {
00859                 es_format_Clean( &tk->fmt );
00860                 if( tk->es ) es_out_Del( p_demux->out, tk->es );
00861             }
00862             tk->b_seen = VLC_FALSE;
00863         }
00864 
00865         if( p_demux->info.i_title != i_title )
00866         {
00867             p_demux->info.i_update |=
00868                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
00869             p_demux->info.i_title = i_title;
00870             p_demux->info.i_seekpoint = 0;
00871         }
00872 
00873         /* TODO: re-add angles */
00874 
00875 
00876         ESNew( p_demux, 0xe0, 0 ); /* Video, FIXME ? */
00877         p_sys->i_aspect = p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio;
00878 
00879 #define audio_control \
00880     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
00881 
00882         /* Audio ES, in the order they appear in the .ifo */
00883         for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams; i++ )
00884         {
00885             int i_position = 0;
00886             uint16_t i_id;
00887 
00888             //IfoPrintAudio( p_demux, i );
00889 
00890             /* Audio channel is active if first byte is 0x80 */
00891             if( audio_control & 0x8000 )
00892             {
00893                 i_position = ( audio_control & 0x7F00 ) >> 8;
00894 
00895                 msg_Dbg( p_demux, "audio position  %d", i_position );
00896                 switch( p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format )
00897                 {
00898                 case 0x00: /* A52 */
00899                     i_id = (0x80 + i_position) | 0xbd00;
00900                     break;
00901                 case 0x02:
00902                 case 0x03: /* MPEG audio */
00903                     i_id = 0xc000 + i_position;
00904                     break;
00905                 case 0x04: /* LPCM */
00906                     i_id = (0xa0 + i_position) | 0xbd00;
00907                     break;
00908                 case 0x06: /* DTS */
00909                     i_id = (0x88 + i_position) | 0xbd00;
00910                     break;
00911                 default:
00912                     i_id = 0;
00913                     msg_Err( p_demux, "unknown audio type %.2x",
00914                         p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format );
00915                 }
00916 
00917                 ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
00918                        vts_audio_attr[i - 1].lang_code );
00919             }
00920         }
00921 #undef audio_control
00922 
00923 #define spu_palette \
00924     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->palette
00925 
00926         memcpy( p_sys->clut, spu_palette, 16 * sizeof( uint32_t ) );
00927 
00928 #define spu_control \
00929     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i-1]
00930 
00931         /* Sub Picture ES */
00932         for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
00933         {
00934             int i_position = 0;
00935             uint16_t i_id;
00936 
00937             //IfoPrintSpu( p_sys, i );
00938             msg_Dbg( p_demux, "spu %d 0x%02x", i, spu_control );
00939 
00940             if( spu_control & 0x80000000 )
00941             {
00942                 /*  there are several streams for one spu */
00943                 if( p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
00944                 {
00945                     /* 16:9 */
00946                     switch( p_vts->vtsi_mat->vts_video_attr.permitted_df )
00947                     {
00948                     case 1: /* letterbox */
00949                         i_position = spu_control & 0xff;
00950                         break;
00951                     case 2: /* pan&scan */
00952                         i_position = ( spu_control >> 8 ) & 0xff;
00953                         break;
00954                     default: /* widescreen */
00955                         i_position = ( spu_control >> 16 ) & 0xff;
00956                         break;
00957                     }
00958                 }
00959                 else
00960                 {
00961                     /* 4:3 */
00962                     i_position = ( spu_control >> 24 ) & 0x7F;
00963                 }
00964 
00965                 i_id = (0x20 + i_position) | 0xbd00;
00966 
00967                 ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
00968                        vts_subp_attr[i - 1].lang_code );
00969             }
00970         }
00971 #undef spu_control
00972 
00973     }
00974     else if( i_title != -1 && i_title != p_sys->i_title )
00975 
00976     {
00977         return VLC_EGENERIC; /* Couldn't set title */
00978     }
00979 
00980     /*
00981      * Chapter selection
00982      */
00983 
00984     if( i_chapter >= 0 && i_chapter < p_sys->i_chapters )
00985     {
00986         pgc_id = p_vts->vts_ptt_srpt->title[
00987                      p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
00988         pgn = p_vts->vts_ptt_srpt->title[
00989                   p_sys->i_ttn - 1].ptt[i_chapter].pgn;
00990 
00991         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
00992 
00993         p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
00994         p_sys->i_chapter = i_chapter;
00995         DvdReadFindCell( p_demux );
00996 
00997         p_sys->i_title_offset = 0;
00998         for( i = p_sys->i_title_start_cell; i < p_sys->i_cur_cell; i++ )
00999         {
01000             p_sys->i_title_offset += p_pgc->cell_playback[i].last_sector -
01001                 p_pgc->cell_playback[i].first_sector + 1;
01002         }
01003 
01004         p_sys->i_pack_len = 0;
01005         p_sys->i_next_vobu = p_sys->i_cur_block =
01006             p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
01007 
01008         if( p_demux->info.i_seekpoint != i_chapter )
01009         {
01010             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
01011             p_demux->info.i_seekpoint = i_chapter;
01012         }
01013     }
01014     else if( i_chapter != -1 )
01015 
01016     {
01017         return VLC_EGENERIC; /* Couldn't set chapter */
01018     }
01019 
01020 #undef p_pgc
01021 #undef p_vts
01022 #undef p_vmg
01023 
01024     return VLC_SUCCESS;
01025 }
01026 
01027 /*****************************************************************************
01028  * DvdReadSeek : Goes to a given position on the stream.
01029  *****************************************************************************
01030  * This one is used by the input and translate chronological position from
01031  * input to logical position on the device.
01032  *****************************************************************************/
01033 static void DvdReadSeek( demux_t *p_demux, int i_block_offset )
01034 {
01035     demux_sys_t *p_sys = p_demux->p_sys;
01036     int i_chapter = 0;
01037     int i_cell = 0;
01038     int i_vobu = 0;
01039     int i_sub_cell = 0;
01040     int i_block;
01041 
01042 #define p_pgc p_sys->p_cur_pgc
01043 #define p_vts p_sys->p_vts_file
01044 
01045     /* Find cell */
01046     i_block = i_block_offset;
01047     for( i_cell = p_sys->i_title_start_cell;
01048          i_cell <= p_sys->i_title_end_cell; i_cell++ )
01049     {
01050         if( i_block < (int)p_pgc->cell_playback[i_cell].last_sector -
01051             (int)p_pgc->cell_playback[i_cell].first_sector + 1 ) break;
01052 
01053         i_block -= (p_pgc->cell_playback[i_cell].last_sector -
01054             p_pgc->cell_playback[i_cell].first_sector + 1);
01055     }
01056     if( i_cell > p_sys->i_title_end_cell )
01057     {
01058         msg_Err( p_demux, "couldn't find cell for block %i", i_block_offset );
01059         return;
01060     }
01061     i_block += p_pgc->cell_playback[i_cell].first_sector;
01062     p_sys->i_title_offset = i_block_offset;
01063 
01064     /* Find chapter */
01065     for( i_chapter = 0; i_chapter < p_sys->i_chapters; i_chapter++ )
01066     {
01067         int pgc_id, pgn, i_tmp;
01068 
01069         pgc_id = p_vts->vts_ptt_srpt->title[
01070                     p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
01071         pgn = p_vts->vts_ptt_srpt->title[
01072                     p_sys->i_ttn - 1].ptt[i_chapter].pgn;
01073 
01074         i_tmp = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc->program_map[pgn-1];
01075 
01076         if( i_tmp > i_cell ) break;
01077     }
01078 
01079     if( i_chapter < p_sys->i_chapters &&
01080         p_demux->info.i_seekpoint != i_chapter )
01081     {
01082         p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
01083         p_demux->info.i_seekpoint = i_chapter;
01084     }
01085 
01086     /* Find vobu */
01087     while( (int)p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu] <= i_block )
01088     {
01089         i_vobu++;
01090     }
01091 
01092     /* Find sub_cell */
01093     while( p_vts->vts_c_adt->cell_adr_table[i_sub_cell].start_sector <
01094            p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu-1] )
01095     {
01096         i_sub_cell++;
01097     }
01098 
01099 #if 1
01100     msg_Dbg( p_demux, "cell %d i_sub_cell %d chapter %d vobu %d "
01101              "cell_sector %d vobu_sector %d sub_cell_sector %d",
01102              i_cell, i_sub_cell, i_chapter, i_vobu,
01103              p_sys->p_cur_pgc->cell_playback[i_cell].first_sector,
01104              p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu],
01105              p_vts->vts_c_adt->cell_adr_table[i_sub_cell - 1].start_sector);
01106 #endif
01107 
01108     p_sys->i_cur_block = i_block;
01109     p_sys->i_next_vobu = p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu];
01110     p_sys->i_pack_len = p_sys->i_next_vobu - i_block;
01111     p_sys->i_cur_cell = i_cell;
01112     p_sys->i_chapter = i_chapter;
01113     DvdReadFindCell( p_demux );
01114 
01115 #undef p_vts
01116 #undef p_pgc
01117 
01118     return;
01119 }
01120 
01121 /*****************************************************************************
01122  * DvdReadHandleDSI
01123  *****************************************************************************/
01124 static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
01125 {
01126     demux_sys_t *p_sys = p_demux->p_sys;
01127 
01128     navRead_DSI( &p_sys->dsi_pack, &p_data[DSI_START_BYTE] );
01129 
01130     /*
01131      * Determine where we go next.  These values are the ones we mostly
01132      * care about.
01133      */
01134     p_sys->i_cur_block = p_sys->dsi_pack.dsi_gi.nv_pck_lbn;
01135     p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
01136 
01137     /*
01138      * Store the timecodes so we can get the current time
01139      */
01140     p_sys->i_title_cur_time = (mtime_t) (p_sys->dsi_pack.dsi_gi.nv_pck_scr / 90 * 1000);
01141     p_sys->i_cell_cur_time = (mtime_t) dvdtime_to_time( &p_sys->dsi_pack.dsi_gi.c_eltm, 0 );
01142 
01143     /*
01144      * If we're not at the end of this cell, we can determine the next
01145      * VOBU to display using the VOBU_SRI information section of the
01146      * DSI.  Using this value correctly follows the current angle,
01147      * avoiding the doubled scenes in The Matrix, and makes our life
01148      * really happy.
01149      */
01150 
01151     p_sys->i_next_vobu = p_sys->i_cur_block +
01152         ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
01153 
01154     if( p_sys->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL
01155         && p_sys->i_angle > 1 )
01156     {
01157         switch( ( p_sys->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
01158         {
01159         case 0x4:
01160             /* Interleaved unit with no angle */
01161             if( p_sys->dsi_pack.sml_pbi.ilvu_sa != 0 )
01162             {
01163                 p_sys->i_next_vobu = p_sys->i_cur_block +
01164                     p_sys->dsi_pack.sml_pbi.ilvu_sa;
01165                 p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
01166             }
01167             else
01168             {
01169                 p_sys->i_next_vobu = p_sys->i_cur_block +
01170                     p_sys->dsi_pack.dsi_gi.vobu_ea + 1;
01171             }
01172             break;
01173         case 0x5:
01174             /* vobu is end of ilvu */
01175             if( p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address )
01176             {
01177                 p_sys->i_next_vobu = p_sys->i_cur_block +
01178                     p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address;
01179                 p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
01180 
01181                 break;
01182             }
01183         case 0x6:
01184             /* vobu is beginning of ilvu */
01185         case 0x9:
01186             /* next scr is 0 */
01187         case 0xa:
01188             /* entering interleaved section */
01189         case 0x8:
01190             /* non interleaved cells in interleaved section */
01191         default:
01192             p_sys->i_next_vobu = p_sys->i_cur_block +
01193                 ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
01194             break;
01195         }
01196     }
01197     else if( p_sys->dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL )
01198     {
01199         p_sys->i_cur_cell = p_sys->i_next_cell;
01200 
01201         /* End of title */
01202         if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells ) return;
01203 
01204         DvdReadFindCell( p_demux );
01205 
01206         p_sys->i_next_vobu =
01207             p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
01208 
01209         p_sys->i_cell_duration = (mtime_t)dvdtime_to_time( &p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].playback_time, 0 );
01210     }
01211 
01212 
01213 #if 0
01214     msg_Dbg( p_demux, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d c_time %lld",
01215              p_sys->dsi_pack.dsi_gi.nv_pck_scr,
01216              p_sys->dsi_pack.dsi_gi.nv_pck_lbn,
01217              p_sys->dsi_pack.dsi_gi.vobu_ea,
01218              p_sys->dsi_pack.dsi_gi.vobu_vob_idn,
01219              p_sys->dsi_pack.dsi_gi.vobu_c_idn,
01220              dvdtime_to_time( &p_sys->dsi_pack.dsi_gi.c_eltm, 0 ) );
01221 
01222     msg_Dbg( p_demux, "cell duration: %lld", 
01223              (mtime_t)dvdtime_to_time( &p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].playback_time, 0 ) );
01224 
01225     msg_Dbg( p_demux, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
01226              p_sys->dsi_pack.sml_pbi.category,
01227              p_sys->dsi_pack.sml_pbi.ilvu_ea,
01228              p_sys->dsi_pack.sml_pbi.ilvu_sa,
01229              p_sys->dsi_pack.sml_pbi.size );
01230 
01231     msg_Dbg( p_demux, "next_vobu %d next_ilvu1 %d next_ilvu2 %d",
01232              p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff,
01233              p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle - 1 ].address,
01234              p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle ].address);
01235 #endif
01236 }
01237 
01238 /*****************************************************************************
01239  * DvdReadFindCell
01240  *****************************************************************************/
01241 static void DvdReadFindCell( demux_t *p_demux )
01242 {
01243     demux_sys_t *p_sys = p_demux->p_sys;
01244 
01245     pgc_t *p_pgc;
01246     int   pgc_id, pgn;
01247     int   i = 0;
01248 
01249 #define cell p_sys->p_cur_pgc->cell_playback
01250 
01251     if( cell[p_sys->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
01252     {
01253         p_sys->i_cur_cell += p_sys->i_angle - 1;
01254 
01255         while( cell[p_sys->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL )
01256         {
01257             i++;
01258         }
01259         p_sys->i_next_cell = p_sys->i_cur_cell + i + 1;
01260     }
01261     else
01262     {
01263         p_sys->i_next_cell = p_sys->i_cur_cell + 1;
01264     }
01265 
01266 #undef cell
01267 
01268     if( p_sys->i_chapter + 1 >= p_sys->i_chapters ) return;
01269 
01270     pgc_id = p_sys->p_vts_file->vts_ptt_srpt->title[
01271                 p_sys->i_ttn - 1].ptt[p_sys->i_chapter + 1].pgcn;
01272     pgn = p_sys->p_vts_file->vts_ptt_srpt->title[
01273               p_sys->i_ttn - 1].ptt[p_sys->i_chapter + 1].pgn;
01274     p_pgc = p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
01275 
01276     if( p_sys->i_cur_cell >= p_pgc->program_map[pgn - 1] - 1 )
01277     {
01278         p_sys->i_chapter++;
01279 
01280         if( p_sys->i_chapter < p_sys->i_chapters &&
01281             p_demux->info.i_seekpoint != p_sys->i_chapter )
01282         {
01283             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
01284             p_demux->info.i_seekpoint = p_sys->i_chapter;
01285         }
01286     }
01287 }
01288 
01289 /*****************************************************************************
01290  * DemuxTitles: get the titles/chapters structure
01291  *****************************************************************************/
01292 static void DemuxTitles( demux_t *p_demux, int *pi_angle )
01293 {
01294     demux_sys_t *p_sys = p_demux->p_sys;
01295     input_title_t *t;
01296     seekpoint_t *s;
01297     int32_t i_titles;
01298     int i;
01299 
01300     /* Find out number of titles/chapters */
01301 #define tt_srpt p_sys->p_vmg_file->tt_srpt
01302 
01303     i_titles = tt_srpt->nr_of_srpts;
01304     msg_Dbg( p_demux, "number of titles: %d", i_titles );
01305 
01306     for( i = 0; i < i_titles; i++ )
01307     {
01308         int32_t i_chapters = 0;
01309         int j;
01310 
01311         i_chapters = tt_srpt->title[i].nr_of_ptts;
01312         msg_Dbg( p_demux, "title %d has %d chapters", i, i_chapters );
01313 
01314         t = vlc_input_title_New();
01315 
01316         for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
01317         {
01318             s = vlc_seekpoint_New();
01319             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
01320         }
01321 
01322         TAB_APPEND( p_sys->i_titles, p_sys->titles, t );
01323     }
01324 
01325 #undef tt_srpt
01326 }

Generated on Tue Dec 20 10:14:24 2005 for vlc-0.8.4a by  doxygen 1.4.2