dvdread.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:39k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * dvdread.c : DvdRead input module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2004 VideoLAN
  5.  * $Id: dvdread.c 8768 2004-09-22 13:43:03Z gbazin $
  6.  *
  7.  * Authors: St閜hane Borel <stef@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdio.h>
  28. #include <stdlib.h>                                      /* malloc(), free() */
  29. #include <string.h>                                              /* strdup() */
  30. #include <vlc/vlc.h>
  31. #include <vlc/input.h>
  32. #include "iso_lang.h"
  33. #include "../demux/ps.h"
  34. #ifdef HAVE_UNISTD_H
  35. #   include <unistd.h>
  36. #endif
  37. #include <fcntl.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <string.h>
  41. #include <dvdread/dvd_reader.h>
  42. #include <dvdread/ifo_types.h>
  43. #include <dvdread/ifo_read.h>
  44. #include <dvdread/nav_read.h>
  45. #include <dvdread/nav_print.h>
  46. /*****************************************************************************
  47.  * Module descriptor
  48.  *****************************************************************************/
  49. #define ANGLE_TEXT N_("DVD angle")
  50. #define ANGLE_LONGTEXT N_( 
  51.     "Allows you to select the default DVD angle." )
  52. #define CACHING_TEXT N_("Caching value in ms")
  53. #define CACHING_LONGTEXT N_( 
  54.     "Allows you to modify the default caching value for DVDread streams. " 
  55.     "This value should be set in millisecond units." )
  56. #define CSSMETHOD_TEXT N_("Method used by libdvdcss for decryption")
  57. #define CSSMETHOD_LONGTEXT N_( 
  58.     "Set the method used by libdvdcss for key decryption.n" 
  59.     "title: decrypted title key is guessed from the encrypted sectors of " 
  60.            "the stream. Thus it should work with a file as well as the " 
  61.            "DVD device. But it sometimes takes much time to decrypt a title " 
  62.            "key and may even fail. With this method, the key is only checked "
  63.            "at the beginning of each title, so it won't work if the key " 
  64.            "changes in the middle of a title.n" 
  65.     "disc: the disc key is first cracked, then all title keys can be " 
  66.            "decrypted instantly, which allows us to check them often.n" 
  67.     "key: the same as "disc" if you don't have a file with player keys " 
  68.            "at compilation time. If you do, the decryption of the disc key " 
  69.            "will be faster with this method. It is the one that was used by " 
  70.            "libcss.n" 
  71.     "The default method is: key.")
  72. static char *psz_css_list[] = { "title", "disc", "key" };
  73. static char *psz_css_list_text[] = { N_("title"), N_("Disc"), N_("Key") };
  74. static int  Open ( vlc_object_t * );
  75. static void Close( vlc_object_t * );
  76. vlc_module_begin();
  77.     set_description( _("DVDRead Input") );
  78.     add_integer( "dvdread-angle", 1, NULL, ANGLE_TEXT,
  79.         ANGLE_LONGTEXT, VLC_FALSE );
  80.     add_integer( "dvdread-caching", DEFAULT_PTS_DELAY / 1000, NULL,
  81.         CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
  82.     add_string( "dvdread-css-method", NULL, NULL, CSSMETHOD_TEXT,
  83.                 CSSMETHOD_LONGTEXT, VLC_TRUE );
  84.         change_string_list( psz_css_list, psz_css_list_text, 0 );
  85.     set_capability( "access_demux", 0 );
  86.     add_shortcut( "dvd" );
  87.     add_shortcut( "dvdread" );
  88.     add_shortcut( "dvdsimple" );
  89.     set_callbacks( Open, Close );
  90. vlc_module_end();
  91. /* how many blocks DVDRead will read in each loop */
  92. #define DVD_BLOCK_READ_ONCE 4
  93. /*****************************************************************************
  94.  * Local prototypes
  95.  *****************************************************************************/
  96. struct demux_sys_t
  97. {
  98.     /* DVDRead state */
  99.     dvd_reader_t *p_dvdread;
  100.     dvd_file_t   *p_title;
  101.     ifo_handle_t *p_vmg_file;
  102.     ifo_handle_t *p_vts_file;
  103.     int i_title;
  104.     int i_chapter, i_chapters;
  105.     int i_angle, i_angles;
  106.     tt_srpt_t    *p_tt_srpt;
  107.     pgc_t        *p_cur_pgc;
  108.     dsi_t        dsi_pack;
  109.     int          i_ttn;
  110.     int i_pack_len;
  111.     int i_cur_block;
  112.     int i_next_vobu;
  113.     /* Current title start/end blocks */
  114.     int i_title_start_block;
  115.     int i_title_end_block;
  116.     int i_title_blocks;
  117.     int i_title_offset;
  118.     int i_title_start_cell;
  119.     int i_title_end_cell;
  120.     int i_cur_cell;
  121.     int i_next_cell;
  122.     /* Track */
  123.     ps_track_t    tk[PS_TK_COUNT];
  124.     int           i_mux_rate;
  125.     int           i_titles;
  126.     input_title_t **titles;
  127.     /* Video */
  128.     int i_aspect;
  129.     /* SPU */
  130.     uint32_t clut[16];
  131. };
  132. static int Control   ( demux_t *, int, va_list );
  133. static int Demux     ( demux_t * );
  134. static int DemuxBlock( demux_t *, uint8_t *, int );
  135. static void DemuxTitles( demux_t *, int * );
  136. static void ESNew( demux_t *, int, int );
  137. static int  DvdReadSetArea  ( demux_t *, int, int, int );
  138. static void DvdReadSeek     ( demux_t *, int );
  139. static void DvdReadHandleDSI( demux_t *, uint8_t * );
  140. static void DvdReadFindCell ( demux_t * );
  141. /*****************************************************************************
  142.  * Open:
  143.  *****************************************************************************/
  144. static int Open( vlc_object_t *p_this )
  145. {
  146.     demux_t      *p_demux = (demux_t*)p_this;
  147.     demux_sys_t  *p_sys;
  148.     char         *psz_name;
  149.     char         *psz_dvdcss_env;
  150.     dvd_reader_t *p_dvdread;
  151.     ifo_handle_t *p_vmg_file;
  152.     vlc_value_t  val;
  153.     if( !p_demux->psz_path || !*p_demux->psz_path )
  154.     {
  155.         /* Only when selected */
  156.         if( !p_this->b_force ) return VLC_EGENERIC;
  157.         psz_name = var_CreateGetString( p_this, "dvd" );
  158.         if( !psz_name || !*psz_name )
  159.         {
  160.             if( psz_name ) free( psz_name );
  161.             return VLC_EGENERIC;
  162.         }
  163.     }
  164.     else psz_name = strdup( p_demux->psz_path );
  165. #ifdef WIN32
  166.     if( psz_name[0] && psz_name[1] == ':' &&
  167.         psz_name[2] == '\' && psz_name[3] == '' ) psz_name[2] = '';
  168. #endif
  169.     /* Override environment variable DVDCSS_METHOD with config option
  170.      * (FIXME: this creates a small memory leak) */
  171.     psz_dvdcss_env = config_GetPsz( p_demux, "dvdread-css-method" );
  172.     if( psz_dvdcss_env && *psz_dvdcss_env )
  173.     {
  174.         char *psz_env;
  175.         psz_env = malloc( strlen("DVDCSS_METHOD=") +
  176.                           strlen( psz_dvdcss_env ) + 1 );
  177.         if( !psz_env )
  178.         {
  179.             free( psz_dvdcss_env );
  180.             return VLC_ENOMEM;
  181.         }
  182.         sprintf( psz_env, "%s%s", "DVDCSS_METHOD=", psz_dvdcss_env );
  183.         putenv( psz_env );
  184.     }
  185.     if( psz_dvdcss_env ) free( psz_dvdcss_env );
  186.     /* Open dvdread */
  187.     if( !(p_dvdread = DVDOpen( psz_name )) )
  188.     {
  189.         msg_Err( p_demux, "DVDRead cannot open source: %s", psz_name );
  190.         free( psz_name );
  191.         return VLC_EGENERIC;
  192.     }
  193.     free( psz_name );
  194.     /* Ifo allocation & initialisation */
  195.     if( !( p_vmg_file = ifoOpen( p_dvdread, 0 ) ) )
  196.     {
  197.         msg_Warn( p_demux, "cannot open VMG info" );
  198.         return VLC_EGENERIC;
  199.     }
  200.     msg_Dbg( p_demux, "VMG opened" );
  201.     /* Fill p_demux field */
  202.     p_demux->pf_demux = Demux;
  203.     p_demux->pf_control = Control;
  204.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  205.     memset( p_sys, 0, sizeof( demux_sys_t ) );
  206.     ps_track_init( p_sys->tk );
  207.     p_sys->i_aspect = -1;
  208.     p_sys->i_mux_rate = 0;
  209.     p_sys->p_dvdread = p_dvdread;
  210.     p_sys->p_vmg_file = p_vmg_file;
  211.     p_sys->p_title = NULL;
  212.     p_sys->p_vts_file = NULL;
  213.     p_sys->i_title = p_sys->i_chapter = -1;
  214.     var_Create( p_demux, "dvdread-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
  215.     var_Get( p_demux, "dvdread-angle", &val );
  216.     p_sys->i_angle = val.i_int > 0 ? val.i_int : 1;
  217.     DemuxTitles( p_demux, &p_sys->i_angle );
  218.     DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle );
  219.     /* Update default_pts to a suitable value for dvdread access */
  220.     var_Create( p_demux, "dvdread-caching",
  221.                 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
  222.     return VLC_SUCCESS;
  223. }
  224. /*****************************************************************************
  225.  * Close:
  226.  *****************************************************************************/
  227. static void Close( vlc_object_t *p_this )
  228. {
  229.     demux_t     *p_demux = (demux_t*)p_this;
  230.     demux_sys_t *p_sys = p_demux->p_sys;
  231.     int i;
  232.     for( i = 0; i < PS_TK_COUNT; i++ )
  233.     {
  234.         ps_track_t *tk = &p_sys->tk[i];
  235.         if( tk->b_seen )
  236.         {
  237.             es_format_Clean( &tk->fmt );
  238.             if( tk->es ) es_out_Del( p_demux->out, tk->es );
  239.         }
  240.     }
  241.     /* Close libdvdread */
  242.     if( p_sys->p_title ) DVDCloseFile( p_sys->p_title );
  243.     if( p_sys->p_vts_file ) ifoClose( p_sys->p_vts_file );
  244.     if( p_sys->p_vmg_file ) ifoClose( p_sys->p_vmg_file );
  245.     DVDClose( p_sys->p_dvdread );
  246.     free( p_sys );
  247. }
  248. /*****************************************************************************
  249.  * Control:
  250.  *****************************************************************************/
  251. static int Control( demux_t *p_demux, int i_query, va_list args )
  252. {
  253.     demux_sys_t *p_sys = p_demux->p_sys;
  254.     double f, *pf;
  255.     vlc_bool_t *pb;
  256.     int64_t *pi64;
  257.     input_title_t ***ppp_title;
  258.     int *pi_int;
  259.     int i;
  260.     switch( i_query )
  261.     {
  262.         case DEMUX_GET_POSITION:
  263.         {
  264.             pf = (double*) va_arg( args, double* );
  265.             if( p_sys->i_title_blocks > 0 )
  266.                 *pf = (double)p_sys->i_title_offset / p_sys->i_title_blocks;
  267.             else
  268.                 *pf = 0.0;
  269.             return VLC_SUCCESS;
  270.         }
  271.         case DEMUX_SET_POSITION:
  272.         {
  273.             f = (double)va_arg( args, double );
  274.             DvdReadSeek( p_demux, f * p_sys->i_title_blocks );
  275.             return VLC_SUCCESS;
  276.         }
  277.         case DEMUX_GET_TIME:
  278.             pi64 = (int64_t*)va_arg( args, int64_t * );
  279.             if( p_sys->i_mux_rate > 0 )
  280.             {
  281.                 *pi64 = (int64_t)1000000 * DVD_VIDEO_LB_LEN *
  282.                         p_sys->i_title_offset / 50 / p_sys->i_mux_rate;
  283.                 return VLC_SUCCESS;
  284.             }
  285.             *pi64 = 0;
  286.             return VLC_EGENERIC;
  287.         case DEMUX_GET_LENGTH:
  288.             pi64 = (int64_t*)va_arg( args, int64_t * );
  289.             if( p_sys->i_mux_rate > 0 )
  290.             {
  291.                 *pi64 = (int64_t)1000000 * DVD_VIDEO_LB_LEN *
  292.                         p_sys->i_title_blocks / 50 / p_sys->i_mux_rate;
  293.                 return VLC_SUCCESS;
  294.             }
  295.             *pi64 = 0;
  296.             return VLC_EGENERIC;
  297.         /* Special for access_demux */
  298.         case DEMUX_CAN_PAUSE:
  299.         case DEMUX_CAN_CONTROL_PACE:
  300.             /* TODO */
  301.             pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
  302.             *pb = VLC_TRUE;
  303.             return VLC_SUCCESS;
  304.         case DEMUX_SET_PAUSE_STATE:
  305.             return VLC_SUCCESS;
  306.         case DEMUX_GET_TITLE_INFO:
  307.             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
  308.             pi_int    = (int*)va_arg( args, int* );
  309.             *((int*)va_arg( args, int* )) = 1; /* Title offset */
  310.             *((int*)va_arg( args, int* )) = 1; /* Chapter offset */
  311.             /* Duplicate title infos */
  312.             *pi_int = p_sys->i_titles;
  313.             *ppp_title = malloc( sizeof(input_title_t **) * p_sys->i_titles );
  314.             for( i = 0; i < p_sys->i_titles; i++ )
  315.             {
  316.                 (*ppp_title)[i] = vlc_input_title_Duplicate(p_sys->titles[i]);
  317.             }
  318.             return VLC_SUCCESS;
  319.         case DEMUX_SET_TITLE:
  320.             i = (int)va_arg( args, int );
  321.             if( DvdReadSetArea( p_demux, i, 0, -1 ) != VLC_SUCCESS )
  322.             {
  323.                 msg_Warn( p_demux, "cannot set title/chapter" );
  324.                 return VLC_EGENERIC;
  325.             }
  326.             p_demux->info.i_update |=
  327.                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
  328.             p_demux->info.i_title = i;
  329.             p_demux->info.i_seekpoint = 0;
  330.             return VLC_SUCCESS;
  331.         case DEMUX_SET_SEEKPOINT:
  332.             i = (int)va_arg( args, int );
  333.             if( DvdReadSetArea( p_demux, -1, i, -1 ) != VLC_SUCCESS )
  334.             {
  335.                 msg_Warn( p_demux, "cannot set title/chapter" );
  336.                 return VLC_EGENERIC;
  337.             }
  338.             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
  339.             p_demux->info.i_seekpoint = i;
  340.             return VLC_SUCCESS;
  341.         case DEMUX_GET_PTS_DELAY:
  342.             pi64 = (int64_t*)va_arg( args, int64_t * );
  343.             *pi64 = (int64_t)var_GetInteger( p_demux, "dvdread-caching" )*1000;
  344.             return VLC_SUCCESS;
  345.         /* TODO implement others */
  346.         default:
  347.             return VLC_EGENERIC;
  348.     }
  349. }
  350. /*****************************************************************************
  351.  * Demux:
  352.  *****************************************************************************/
  353. static int Demux( demux_t *p_demux )
  354. {
  355.     demux_sys_t *p_sys = p_demux->p_sys;
  356.     uint8_t p_buffer[DVD_VIDEO_LB_LEN * DVD_BLOCK_READ_ONCE];
  357.     int i_blocks_once, i_read;
  358.     int i;
  359.     /*
  360.      * Playback by cell in this pgc, starting at the cell for our chapter.
  361.      */
  362.     /*
  363.      * Check end of pack, and select the following one
  364.      */
  365.     if( !p_sys->i_pack_len )
  366.     {
  367.         /* Read NAV packet */
  368.         if( DVDReadBlocks( p_sys->p_title, p_sys->i_next_vobu,
  369.                            1, p_buffer ) != 1 )
  370.         {
  371.             msg_Err( p_demux, "read failed for block %d", p_sys->i_next_vobu );
  372.             return -1;
  373.         }
  374.         /* Basic check to be sure we don't have a empty title
  375.          * go to next title if so */
  376.         //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
  377.         /* Parse the contained dsi packet */
  378.         DvdReadHandleDSI( p_demux, p_buffer );
  379.         /* End of title */
  380.         if( p_sys->i_next_vobu > p_sys->i_title_end_block )
  381.         {
  382.             if( p_sys->i_title + 1 >= p_sys->i_titles )
  383.             {
  384.                 return 0; /* EOF */
  385.             }
  386.             DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
  387.         }
  388.         if( p_sys->i_pack_len >= 1024 )
  389.         {
  390.             msg_Err( p_demux, "i_pack_len >= 1024 (%i). "
  391.                      "This shouldn't happen!", p_sys->i_pack_len );
  392.             return 0; /* EOF */
  393.         }
  394.         /* FIXME: Ugly kludge: we send the pack block to the input for it
  395.          * sometimes has a zero scr and restart the sync */
  396.         p_sys->i_cur_block++;
  397.         p_sys->i_title_offset++;
  398.         DemuxBlock( p_demux, p_buffer, DVD_VIDEO_LB_LEN );
  399.     }
  400.     if( p_sys->i_cur_block > p_sys->i_title_end_block )
  401.     {
  402.         if( p_sys->i_title + 1 >= p_sys->i_titles )
  403.         {
  404.             return 0; /* EOF */
  405.         }
  406.         DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
  407.     }
  408.     /*
  409.      * Read actual data
  410.      */
  411.     i_blocks_once = __MIN( p_sys->i_pack_len, DVD_BLOCK_READ_ONCE );
  412.     p_sys->i_pack_len -= i_blocks_once;
  413.     /* Reads from DVD */
  414.     i_read = DVDReadBlocks( p_sys->p_title, p_sys->i_cur_block,
  415.                             i_blocks_once, p_buffer );
  416.     if( i_read != i_blocks_once )
  417.     {
  418.         msg_Err( p_demux, "read failed for %d/%d blocks at 0x%02x",
  419.                  i_read, i_blocks_once, p_sys->i_cur_block );
  420.         return -1;
  421.     }
  422.     p_sys->i_cur_block += i_read;
  423.     p_sys->i_title_offset += i_read;
  424. #if 0
  425.     msg_Dbg( p_demux, "i_blocks: %d len: %d current: 0x%02x",
  426.              i_read, p_sys->i_pack_len, p_sys->i_cur_block );
  427. #endif
  428.     for( i = 0; i < i_read; i++ )
  429.     {
  430.         DemuxBlock( p_demux, p_buffer + i * DVD_VIDEO_LB_LEN,
  431.                     DVD_VIDEO_LB_LEN );
  432.     }
  433. #undef p_pgc
  434.     return 1;
  435. }
  436. /*****************************************************************************
  437.  * DemuxBlock: demux a given block
  438.  *****************************************************************************/
  439. static int DemuxBlock( demux_t *p_demux, uint8_t *pkt, int i_pkt )
  440. {
  441.     demux_sys_t *p_sys = p_demux->p_sys;
  442.     uint8_t     *p = pkt;
  443.     while( p < &pkt[i_pkt] )
  444.     {
  445.         int i_size = ps_pkt_size( p, &pkt[i_pkt] - p );
  446.         block_t *p_pkt;
  447.         if( i_size <= 0 )
  448.         {
  449.             break;
  450.         }
  451.         /* Create a block */
  452.         p_pkt = block_New( p_demux, i_size );
  453.         memcpy( p_pkt->p_buffer, p, i_size);
  454.         /* Parse it and send it */
  455.         switch( 0x100 | p[3] )
  456.         {
  457.         case 0x1b9:
  458.         case 0x1bb:
  459.         case 0x1bc:
  460. #ifdef DVDREAD_DEBUG
  461.             if( p[3] == 0xbc )
  462.             {
  463.                 msg_Warn( p_demux, "received a PSM packet" );
  464.             }
  465.             else if( p[3] == 0xbb )
  466.             {
  467.                 msg_Warn( p_demux, "received a SYSTEM packet" );
  468.             }
  469. #endif
  470.             block_Release( p_pkt );
  471.             break;
  472.         case 0x1ba:
  473.         {
  474.             int64_t i_scr;
  475.             int i_mux_rate;
  476.             if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) )
  477.             {
  478.                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr );
  479.                 if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
  480.             }
  481.             block_Release( p_pkt );
  482.             break;
  483.         }
  484.         default:
  485.         {
  486.             int i_id = ps_pkt_id( p_pkt );
  487.             if( i_id >= 0xc0 )
  488.             {
  489.                 ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
  490.                 if( !tk->b_seen )
  491.                 {
  492.                     ESNew( p_demux, i_id, 0 );
  493.                 }
  494.                 if( tk->b_seen && tk->es &&
  495.                     !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
  496.                 {
  497.                     es_out_Send( p_demux->out, tk->es, p_pkt );
  498.                 }
  499.                 else
  500.                 {
  501.                     block_Release( p_pkt );
  502.                 }
  503.             }
  504.             else
  505.             {
  506.                 block_Release( p_pkt );
  507.             }
  508.             break;
  509.         }
  510.         }
  511.         p += i_size;
  512.     }
  513.     return VLC_SUCCESS;
  514. }
  515. /*****************************************************************************
  516.  * ESNew: register a new elementary stream
  517.  *****************************************************************************/
  518. static void ESNew( demux_t *p_demux, int i_id, int i_lang )
  519. {
  520.     demux_sys_t *p_sys = p_demux->p_sys;
  521.     ps_track_t  *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
  522.     char psz_language[3];
  523.     if( tk->b_seen ) return;
  524.     if( ps_track_fill( tk, 0, i_id ) )
  525.     {
  526.         msg_Warn( p_demux, "unknown codec for id=0x%x", i_id );
  527.         return;
  528.     }
  529.     psz_language[0] = psz_language[1] = psz_language[2] = 0;
  530.     if( i_lang && i_lang != 0xffff )
  531.     {
  532.         psz_language[0] = (i_lang >> 8)&0xff;
  533.         psz_language[1] = (i_lang     )&0xff;
  534.     }
  535.     /* Add a new ES */
  536.     if( tk->fmt.i_cat == VIDEO_ES )
  537.     {
  538.         if( p_sys->i_aspect >= 0 )
  539.         {
  540.             tk->fmt.video.i_aspect = p_sys->i_aspect;
  541.         }
  542.     }
  543.     else if( tk->fmt.i_cat == AUDIO_ES )
  544.     {
  545.         int i_audio = -1;
  546.         /* find the audio number PLEASE find another way */
  547.         if( (i_id&0xbdf8) == 0xbd88 )       /* dts */
  548.         {
  549.             i_audio = i_id&0x07;
  550.         }
  551.         else if( (i_id&0xbdf0) == 0xbd80 )  /* a52 */
  552.         {
  553.             i_audio = i_id&0xf;
  554.         }
  555.         else if( (i_id&0xbdf0) == 0xbda0 )  /* lpcm */
  556.         {
  557.             i_audio = i_id&0x1f;
  558.         }
  559.         else if( ( i_id&0xe0 ) == 0xc0 )    /* mpga */
  560.         {
  561.             i_audio = i_id&0x1f;
  562.         }
  563.         if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
  564.     }
  565.     else if( tk->fmt.i_cat == SPU_ES )
  566.     {
  567.         /* Palette */
  568.         tk->fmt.subs.spu.palette[0] = 0xBeef;
  569.         memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut,
  570.                 16 * sizeof( uint32_t ) );
  571.         if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
  572.     }
  573.     tk->es = es_out_Add( p_demux->out, &tk->fmt );
  574.     tk->b_seen = VLC_TRUE;
  575. }
  576. /*****************************************************************************
  577.  * DvdReadSetArea: initialize input data for title x, chapter y.
  578.  * It should be called for each user navigation request.
  579.  *****************************************************************************
  580.  * Take care that i_title and i_chapter start from 0.
  581.  *****************************************************************************/
  582. static int DvdReadSetArea( demux_t *p_demux, int i_title, int i_chapter,
  583.                            int i_angle )
  584. {
  585.     demux_sys_t *p_sys = p_demux->p_sys;
  586.     int pgc_id = 0, pgn = 0;
  587.     int i;
  588. #define p_pgc p_sys->p_cur_pgc
  589. #define p_vmg p_sys->p_vmg_file
  590. #define p_vts p_sys->p_vts_file
  591.     if( i_title >= 0 && i_title < p_sys->i_titles &&
  592.         i_title != p_sys->i_title )
  593.     {
  594.         int i_start_cell, i_end_cell;
  595.         if( p_sys->p_title != NULL ) DVDCloseFile( p_sys->p_title );
  596.         if( p_vts != NULL ) ifoClose( p_vts );
  597.         p_sys->i_title = i_title;
  598.         /*
  599.          *  We have to load all title information
  600.          */
  601.         msg_Dbg( p_demux, "open VTS %d, for title %d",
  602.                  p_vmg->tt_srpt->title[i_title].title_set_nr, i_title + 1 );
  603.         /* Ifo vts */
  604.         if( !( p_vts = ifoOpen( p_sys->p_dvdread,
  605.                p_vmg->tt_srpt->title[i_title].title_set_nr ) ) )
  606.         {
  607.             msg_Err( p_demux, "fatal error in vts ifo" );
  608.             return VLC_EGENERIC;
  609.         }
  610.         /* Title position inside the selected vts */
  611.         p_sys->i_ttn = p_vmg->tt_srpt->title[i_title].vts_ttn;
  612.         /* Find title start/end */
  613.         pgc_id = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgcn;
  614.         pgn = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgn;
  615.         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
  616.         p_sys->i_title_start_cell =
  617.             i_start_cell = p_pgc->program_map[pgn - 1] - 1;
  618.         p_sys->i_title_start_block =
  619.             p_pgc->cell_playback[i_start_cell].first_sector;
  620.         p_sys->i_title_end_cell =
  621.             i_end_cell = p_pgc->nr_of_cells - 1;
  622.         p_sys->i_title_end_block =
  623.             p_pgc->cell_playback[i_end_cell].last_sector;
  624.         p_sys->i_title_offset = 0;
  625.         p_sys->i_title_blocks = 0;
  626.         for( i = i_start_cell; i <= i_end_cell; i++ )
  627.         {
  628.             p_sys->i_title_blocks += p_pgc->cell_playback[i].last_sector -
  629.                 p_pgc->cell_playback[i].first_sector + 1;
  630.         }
  631.         msg_Dbg( p_demux, "title %d vts_title %d pgc %d pgn %d "
  632.                  "start %d end %d blocks: %d",
  633.                  i_title + 1, p_sys->i_ttn, pgc_id, pgn,
  634.                  p_sys->i_title_start_block, p_sys->i_title_end_block,
  635.                  p_sys->i_title_blocks );
  636.         /*
  637.          * Set properties for current chapter
  638.          */
  639.         p_sys->i_chapter = 0;
  640.         p_sys->i_chapters =
  641.             p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].nr_of_ptts;
  642.         pgc_id = p_vts->vts_ptt_srpt->title[
  643.                     p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgcn;
  644.         pgn = p_vts->vts_ptt_srpt->title[
  645.                     p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgn;
  646.         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
  647.         p_sys->i_pack_len = 0;
  648.         p_sys->i_next_cell =
  649.             p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
  650.         DvdReadFindCell( p_demux );
  651.         p_sys->i_next_vobu = p_sys->i_cur_block =
  652.             p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
  653.         /*
  654.          * Angle management
  655.          */
  656.         p_sys->i_angles = p_vmg->tt_srpt->title[i_title].nr_of_angles;
  657.         if( p_sys->i_angle > p_sys->i_angles ) p_sys->i_angle = 1;
  658.         /*
  659.          * We've got enough info, time to open the title set data.
  660.          */
  661.         if( !( p_sys->p_title = DVDOpenFile( p_sys->p_dvdread,
  662.             p_vmg->tt_srpt->title[i_title].title_set_nr,
  663.             DVD_READ_TITLE_VOBS ) ) )
  664.         {
  665.             msg_Err( p_demux, "cannot open title (VTS_%02d_1.VOB)",
  666.                      p_vmg->tt_srpt->title[i_title].title_set_nr );
  667.             return VLC_EGENERIC;
  668.         }
  669.         //IfoPrintTitle( p_demux );
  670.         /*
  671.          * Destroy obsolete ES by reinitializing program 0
  672.          * and find all ES in title with ifo data
  673.          */
  674.         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  675.         for( i = 0; i < PS_TK_COUNT; i++ )
  676.         {
  677.             ps_track_t *tk = &p_sys->tk[i];
  678.             if( tk->b_seen )
  679.             {
  680.                 es_format_Clean( &tk->fmt );
  681.                 if( tk->es ) es_out_Del( p_demux->out, tk->es );
  682.             }
  683.             tk->b_seen = VLC_FALSE;
  684.         }
  685.         if( p_demux->info.i_title != i_title )
  686.         {
  687.             p_demux->info.i_update |=
  688.                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
  689.             p_demux->info.i_title = i_title;
  690.             p_demux->info.i_seekpoint = 0;
  691.         }
  692.         /* TODO: re-add angles */
  693.         ESNew( p_demux, 0xe0, 0 ); /* Video, FIXME ? */
  694.         p_sys->i_aspect = p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio;
  695. #define audio_control 
  696.     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
  697.         /* Audio ES, in the order they appear in the .ifo */
  698.         for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams; i++ )
  699.         {
  700.             int i_position = 0;
  701.             uint16_t i_id;
  702.             //IfoPrintAudio( p_demux, i );
  703.             /* Audio channel is active if first byte is 0x80 */
  704.             if( audio_control & 0x8000 )
  705.             {
  706.                 i_position = ( audio_control & 0x7F00 ) >> 8;
  707.                 msg_Dbg( p_demux, "audio position  %d", i_position );
  708.                 switch( p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format )
  709.                 {
  710.                 case 0x00: /* A52 */
  711.                     i_id = (0x80 + i_position) | 0xbd00;
  712.                     break;
  713.                 case 0x02:
  714.                 case 0x03: /* MPEG audio */
  715.                     i_id = 0xc000 + i_position;
  716.                     break;
  717.                 case 0x04: /* LPCM */
  718.                     i_id = (0xa0 + i_position) | 0xbd00;
  719.                     break;
  720.                 case 0x06: /* DTS */
  721.                     i_id = (0x88 + i_position) | 0xbd00;
  722.                     break;
  723.                 default:
  724.                     i_id = 0;
  725.                     msg_Err( p_demux, "unknown audio type %.2x",
  726.                         p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format );
  727.                 }
  728.                 ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
  729.                        vts_audio_attr[i - 1].lang_code );
  730.             }
  731.         }
  732. #undef audio_control
  733. #define spu_palette 
  734.     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->palette
  735.         memcpy( p_sys->clut, spu_palette, 16 * sizeof( uint32_t ) );
  736. #define spu_control 
  737.     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i-1]
  738.         /* Sub Picture ES */
  739.         for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
  740.         {
  741.             int i_position = 0;
  742.             uint16_t i_id;
  743.             //IfoPrintSpu( p_sys, i );
  744.             msg_Dbg( p_demux, "spu %d 0x%02x", i, spu_control );
  745.             if( spu_control & 0x80000000 )
  746.             {
  747.                 /*  there are several streams for one spu */
  748.                 if( p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
  749.                 {
  750.                     /* 16:9 */
  751.                     switch( p_vts->vtsi_mat->vts_video_attr.permitted_df )
  752.                     {
  753.                     case 1: /* letterbox */
  754.                         i_position = spu_control & 0xff;
  755.                         break;
  756.                     case 2: /* pan&scan */
  757.                         i_position = ( spu_control >> 8 ) & 0xff;
  758.                         break;
  759.                     default: /* widescreen */
  760.                         i_position = ( spu_control >> 16 ) & 0xff;
  761.                         break;
  762.                     }
  763.                 }
  764.                 else
  765.                 {
  766.                     /* 4:3 */
  767.                     i_position = ( spu_control >> 24 ) & 0x7F;
  768.                 }
  769.                 i_id = (0x20 + i_position) | 0xbd00;
  770.                 ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
  771.                        vts_subp_attr[i - 1].lang_code );
  772.             }
  773.         }
  774. #undef spu_control
  775.     }
  776.     else if( i_title != -1 && i_title != p_sys->i_title )
  777.     {
  778.         return VLC_EGENERIC; /* Couldn't set title */
  779.     }
  780.     /*
  781.      * Chapter selection
  782.      */
  783.     if( i_chapter >= 0 && i_chapter < p_sys->i_chapters )
  784.     {
  785.         pgc_id = p_vts->vts_ptt_srpt->title[
  786.                      p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
  787.         pgn = p_vts->vts_ptt_srpt->title[
  788.                   p_sys->i_ttn - 1].ptt[i_chapter].pgn;
  789.         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
  790.         p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
  791.         p_sys->i_chapter = i_chapter;
  792.         DvdReadFindCell( p_demux );
  793.         p_sys->i_title_offset = 0;
  794.         for( i = p_sys->i_title_start_cell; i < p_sys->i_cur_cell; i++ )
  795.         {
  796.             p_sys->i_title_offset += p_pgc->cell_playback[i].last_sector -
  797.                 p_pgc->cell_playback[i].first_sector + 1;
  798.         }
  799.         p_sys->i_pack_len = 0;
  800.         p_sys->i_next_vobu = p_sys->i_cur_block =
  801.             p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
  802.         if( p_demux->info.i_seekpoint != i_chapter )
  803.         {
  804.             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
  805.             p_demux->info.i_seekpoint = i_chapter;
  806.         }
  807.     }
  808.     else if( i_chapter != -1 )
  809.     {
  810.         return VLC_EGENERIC; /* Couldn't set chapter */
  811.     }
  812. #undef p_pgc
  813. #undef p_vts
  814. #undef p_vmg
  815.     return VLC_SUCCESS;
  816. }
  817. /*****************************************************************************
  818.  * DvdReadSeek : Goes to a given position on the stream.
  819.  *****************************************************************************
  820.  * This one is used by the input and translate chronological position from
  821.  * input to logical position on the device.
  822.  *****************************************************************************/
  823. static void DvdReadSeek( demux_t *p_demux, int i_block_offset )
  824. {
  825.     demux_sys_t *p_sys = p_demux->p_sys;
  826.     int i_chapter = 0;
  827.     int i_cell = 0;
  828.     int i_vobu = 0;
  829.     int i_sub_cell = 0;
  830.     int i_block;
  831. #define p_pgc p_sys->p_cur_pgc
  832. #define p_vts p_sys->p_vts_file
  833.     /* Find cell */
  834.     i_block = i_block_offset;
  835.     for( i_cell = p_sys->i_title_start_cell;
  836.          i_cell <= p_sys->i_title_end_cell; i_cell++ )
  837.     {
  838.         if( i_block < (int)p_pgc->cell_playback[i_cell].last_sector -
  839.             (int)p_pgc->cell_playback[i_cell].first_sector + 1 ) break;
  840.         i_block -= (p_pgc->cell_playback[i_cell].last_sector -
  841.             p_pgc->cell_playback[i_cell].first_sector + 1);
  842.     }
  843.     if( i_cell > p_sys->i_title_end_cell )
  844.     {
  845.         msg_Err( p_demux, "couldn't find cell for block %i", i_block_offset );
  846.         return;
  847.     }
  848.     i_block += p_pgc->cell_playback[i_cell].first_sector;
  849.     p_sys->i_title_offset = i_block_offset;
  850.     /* Find chapter */
  851.     for( i_chapter = 0; i_chapter < p_sys->i_chapters; i_chapter++ )
  852.     {
  853.         int pgc_id, pgn, i_tmp;
  854.         pgc_id = p_vts->vts_ptt_srpt->title[
  855.                     p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
  856.         pgn = p_vts->vts_ptt_srpt->title[
  857.                     p_sys->i_ttn - 1].ptt[i_chapter].pgn;
  858.         i_tmp = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc->program_map[pgn-1];
  859.         if( i_tmp > i_cell ) break;
  860.     }
  861.     if( i_chapter < p_sys->i_chapters &&
  862.         p_demux->info.i_seekpoint != i_chapter )
  863.     {
  864.         p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
  865.         p_demux->info.i_seekpoint = i_chapter;
  866.     }
  867.     /* Find vobu */
  868.     while( (int)p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu] <= i_block )
  869.     {
  870.         i_vobu++;
  871.     }
  872.     /* Find sub_cell */
  873.     while( p_vts->vts_c_adt->cell_adr_table[i_sub_cell].start_sector <
  874.            p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu-1] )
  875.     {
  876.         i_sub_cell++;
  877.     }
  878. #if 1
  879.     msg_Dbg( p_demux, "cell %d i_sub_cell %d chapter %d vobu %d "
  880.              "cell_sector %d vobu_sector %d sub_cell_sector %d",
  881.              i_cell, i_sub_cell, i_chapter, i_vobu,
  882.              p_sys->p_cur_pgc->cell_playback[i_cell].first_sector,
  883.              p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu],
  884.              p_vts->vts_c_adt->cell_adr_table[i_sub_cell - 1].start_sector);
  885. #endif
  886.     p_sys->i_cur_block = i_block;
  887.     p_sys->i_next_vobu = p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu];
  888.     p_sys->i_pack_len = p_sys->i_next_vobu - i_block;
  889.     p_sys->i_cur_cell = i_cell;
  890.     p_sys->i_chapter = i_chapter;
  891.     DvdReadFindCell( p_demux );
  892. #undef p_vts
  893. #undef p_pgc
  894.     return;
  895. }
  896. /*****************************************************************************
  897.  * DvdReadHandleDSI
  898.  *****************************************************************************/
  899. static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
  900. {
  901.     demux_sys_t *p_sys = p_demux->p_sys;
  902.     navRead_DSI( &p_sys->dsi_pack, &p_data[DSI_START_BYTE] );
  903.     /*
  904.      * Determine where we go next.  These values are the ones we mostly
  905.      * care about.
  906.      */
  907.     p_sys->i_cur_block = p_sys->dsi_pack.dsi_gi.nv_pck_lbn;
  908.     p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
  909.     /*
  910.      * If we're not at the end of this cell, we can determine the next
  911.      * VOBU to display using the VOBU_SRI information section of the
  912.      * DSI.  Using this value correctly follows the current angle,
  913.      * avoiding the doubled scenes in The Matrix, and makes our life
  914.      * really happy.
  915.      */
  916.     p_sys->i_next_vobu = p_sys->i_cur_block +
  917.         ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
  918.     if( p_sys->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL
  919.         && p_sys->i_angle > 1 )
  920.     {
  921.         switch( ( p_sys->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
  922.         {
  923.         case 0x4:
  924.             /* Interleaved unit with no angle */
  925.             if( p_sys->dsi_pack.sml_pbi.ilvu_sa != 0 )
  926.             {
  927.                 p_sys->i_next_vobu = p_sys->i_cur_block +
  928.                     p_sys->dsi_pack.sml_pbi.ilvu_sa;
  929.                 p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
  930.             }
  931.             else
  932.             {
  933.                 p_sys->i_next_vobu = p_sys->i_cur_block +
  934.                     p_sys->dsi_pack.dsi_gi.vobu_ea + 1;
  935.             }
  936.             break;
  937.         case 0x5:
  938.             /* vobu is end of ilvu */
  939.             if( p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address )
  940.             {
  941.                 p_sys->i_next_vobu = p_sys->i_cur_block +
  942.                     p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address;
  943.                 p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
  944.                 break;
  945.             }
  946.         case 0x6:
  947.             /* vobu is beginning of ilvu */
  948.         case 0x9:
  949.             /* next scr is 0 */
  950.         case 0xa:
  951.             /* entering interleaved section */
  952.         case 0x8:
  953.             /* non interleaved cells in interleaved section */
  954.         default:
  955.             p_sys->i_next_vobu = p_sys->i_cur_block +
  956.                 ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
  957.             break;
  958.         }
  959.     }
  960.     else if( p_sys->dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL )
  961.     {
  962.         p_sys->i_cur_cell = p_sys->i_next_cell;
  963.         DvdReadFindCell( p_demux );
  964.         p_sys->i_next_vobu =
  965.             p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
  966.     }
  967. #if 0
  968.     msg_Dbg( p_demux, 12, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d",
  969.              p_sys->dsi_pack.dsi_gi.nv_pck_scr,
  970.              p_sys->dsi_pack.dsi_gi.nv_pck_lbn,
  971.              p_sys->dsi_pack.dsi_gi.vobu_ea,
  972.              p_sys->dsi_pack.dsi_gi.vobu_vob_idn,
  973.              p_sys->dsi_pack.dsi_gi.vobu_c_idn );
  974.     msg_Dbg( p_demux, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
  975.              p_sys->dsi_pack.sml_pbi.category,
  976.              p_sys->dsi_pack.sml_pbi.ilvu_ea,
  977.              p_sys->dsi_pack.sml_pbi.ilvu_sa,
  978.              p_sys->dsi_pack.sml_pbi.size );
  979.     msg_Dbg( p_demux, 12, "next_vobu %d next_ilvu1 %d next_ilvu2 %d",
  980.              p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff,
  981.              p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle - 1 ].address,
  982.              p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle ].address);
  983. #endif
  984. }
  985. /*****************************************************************************
  986.  * DvdReadFindCell
  987.  *****************************************************************************/
  988. static void DvdReadFindCell( demux_t *p_demux )
  989. {
  990.     demux_sys_t *p_sys = p_demux->p_sys;
  991.     pgc_t *p_pgc;
  992.     int   pgc_id, pgn;
  993.     int   i = 0;
  994. #define cell p_sys->p_cur_pgc->cell_playback
  995.     if( cell[p_sys->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
  996.     {
  997.         p_sys->i_cur_cell += p_sys->i_angle - 1;
  998.         while( cell[p_sys->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL )
  999.         {
  1000.             i++;
  1001.         }
  1002.         p_sys->i_next_cell = p_sys->i_cur_cell + i + 1;
  1003.     }
  1004.     else
  1005.     {
  1006.         p_sys->i_next_cell = p_sys->i_cur_cell + 1;
  1007.     }
  1008. #undef cell
  1009.     if( p_sys->i_chapter + 1 >= p_sys->i_chapters ) return;
  1010.     pgc_id = p_sys->p_vts_file->vts_ptt_srpt->title[
  1011.                 p_sys->i_ttn - 1].ptt[p_sys->i_chapter + 1].pgcn;
  1012.     pgn = p_sys->p_vts_file->vts_ptt_srpt->title[
  1013.               p_sys->i_ttn - 1].ptt[p_sys->i_chapter + 1].pgn;
  1014.     p_pgc = p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
  1015.     if( p_sys->i_cur_cell >= p_pgc->program_map[pgn - 1] - 1 )
  1016.     {
  1017.         p_sys->i_chapter++;
  1018.         if( p_sys->i_chapter < p_sys->i_chapters &&
  1019.             p_demux->info.i_seekpoint != p_sys->i_chapter )
  1020.         {
  1021.             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
  1022.             p_demux->info.i_seekpoint = p_sys->i_chapter;
  1023.         }
  1024.     }
  1025. }
  1026. /*****************************************************************************
  1027.  * DemuxTitles: get the titles/chapters structure
  1028.  *****************************************************************************/
  1029. static void DemuxTitles( demux_t *p_demux, int *pi_angle )
  1030. {
  1031.     demux_sys_t *p_sys = p_demux->p_sys;
  1032.     input_title_t *t;
  1033.     seekpoint_t *s;
  1034.     int32_t i_titles;
  1035.     int i;
  1036.     /* Find out number of titles/chapters */
  1037. #define tt_srpt p_sys->p_vmg_file->tt_srpt
  1038.     i_titles = tt_srpt->nr_of_srpts;
  1039.     msg_Dbg( p_demux, "number of titles: %d", i_titles );
  1040.     for( i = 0; i < i_titles; i++ )
  1041.     {
  1042.         int32_t i_chapters = 0;
  1043.         int j;
  1044.         i_chapters = tt_srpt->title[i].nr_of_ptts;
  1045.         msg_Dbg( p_demux, "title %d has %d chapters", i, i_chapters );
  1046.         t = vlc_input_title_New();
  1047.         for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
  1048.         {
  1049.             s = vlc_seekpoint_New();
  1050.             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  1051.         }
  1052.         TAB_APPEND( p_sys->i_titles, p_sys->titles, t );
  1053.     }
  1054. #undef tt_srpt
  1055. }