Headers for newer libdvdread have moved :D
[vlc.git] / modules / access / dvdread.c
1 /*****************************************************************************
2  * dvdread.c : DvdRead input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: St├ęphane 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_input.h>
36 #include <vlc_access.h>
37 #include <vlc_charset.h>
38
39 #include <vlc_interface.h>
40
41 #include <vlc_iso_lang.h>
42
43 #include "../demux/ps.h"
44
45 #ifdef HAVE_UNISTD_H
46 #   include <unistd.h>
47 #endif
48
49 #include <fcntl.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52
53 #ifdef HAVE_DVDREAD_DVD_READER_H
54   #include <dvdread/dvd_reader.h>
55   #include <dvdread/ifo_types.h>
56   #include <dvdread/ifo_read.h>
57   #include <dvdread/nav_read.h>
58   #include <dvdread/nav_print.h>
59 #elif
60   #include <libdvdread/dvd_reader.h>
61   #include <libdvdread/ifo_types.h>
62   #include <libdvdread/ifo_read.h>
63   #include <libdvdread/nav_read.h>
64   #include <libdvdread/nav_print.h>
65 #else
66
67 #include <assert.h>
68
69 /*****************************************************************************
70  * Module descriptor
71  *****************************************************************************/
72 #define ANGLE_TEXT N_("DVD angle")
73 #define ANGLE_LONGTEXT N_( \
74     "Default DVD angle." )
75
76 #define CACHING_TEXT N_("Caching value in ms")
77 #define CACHING_LONGTEXT N_( \
78     "Caching value for DVDs. " \
79     "This value should be set in milliseconds." )
80
81 #define CSSMETHOD_TEXT N_("Method used by libdvdcss for decryption")
82 #define CSSMETHOD_LONGTEXT N_( \
83     "Set the method used by libdvdcss for key decryption.\n" \
84     "title: decrypted title key is guessed from the encrypted sectors of " \
85            "the stream. Thus it should work with a file as well as the " \
86            "DVD device. But it sometimes takes much time to decrypt a title " \
87            "key and may even fail. With this method, the key is only checked "\
88            "at the beginning of each title, so it won't work if the key " \
89            "changes in the middle of a title.\n" \
90     "disc: the disc key is first cracked, then all title keys can be " \
91            "decrypted instantly, which allows us to check them often.\n" \
92     "key: the same as \"disc\" if you don't have a file with player keys " \
93            "at compilation time. If you do, the decryption of the disc key " \
94            "will be faster with this method. It is the one that was used by " \
95            "libcss.\n" \
96     "The default method is: key.")
97
98 static const char *const psz_css_list[] = { "title", "disc", "key" };
99 static const char *const psz_css_list_text[] = { N_("title"), N_("Disc"), N_("Key") };
100
101 static int  Open ( vlc_object_t * );
102 static void Close( vlc_object_t * );
103
104 vlc_module_begin();
105     set_shortname( N_("DVD without menus") );
106     set_description( N_("DVDRead Input (DVD without menu support)") );
107     set_category( CAT_INPUT );
108     set_subcategory( SUBCAT_INPUT_ACCESS );
109     add_integer( "dvdread-angle", 1, NULL, ANGLE_TEXT,
110         ANGLE_LONGTEXT, false );
111     add_integer( "dvdread-caching", DEFAULT_PTS_DELAY / 1000, NULL,
112         CACHING_TEXT, CACHING_LONGTEXT, true );
113     add_string( "dvdread-css-method", NULL, NULL, CSSMETHOD_TEXT,
114                 CSSMETHOD_LONGTEXT, true );
115         change_string_list( psz_css_list, psz_css_list_text, 0 );
116     set_capability( "access_demux", 0 );
117     add_shortcut( "dvd" );
118     add_shortcut( "dvdread" );
119     add_shortcut( "dvdsimple" );
120     set_callbacks( Open, Close );
121 vlc_module_end();
122
123 /* how many blocks DVDRead will read in each loop */
124 #define DVD_BLOCK_READ_ONCE 4
125
126 /*****************************************************************************
127  * Local prototypes
128  *****************************************************************************/
129
130 struct demux_sys_t
131 {
132     /* DVDRead state */
133     dvd_reader_t *p_dvdread;
134     dvd_file_t   *p_title;
135
136     ifo_handle_t *p_vmg_file;
137     ifo_handle_t *p_vts_file;
138
139     int i_title;
140     int i_chapter, i_chapters;
141     int i_angle, i_angles;
142
143     tt_srpt_t    *p_tt_srpt;
144     pgc_t        *p_cur_pgc;
145     dsi_t        dsi_pack;
146     int          i_ttn;
147
148     int i_pack_len;
149     int i_cur_block;
150     int i_next_vobu;
151
152     int i_mux_rate;
153
154     /* Current title start/end blocks */
155     int i_title_start_block;
156     int i_title_end_block;
157     int i_title_blocks;
158     int i_title_offset;
159     mtime_t i_title_cur_time;
160
161     int i_title_start_cell;
162     int i_title_end_cell;
163     int i_cur_cell;
164     int i_next_cell;
165     mtime_t i_cell_cur_time;
166     mtime_t i_cell_duration;
167
168     /* Track */
169     ps_track_t    tk[PS_TK_COUNT];
170
171     int           i_titles;
172     input_title_t **titles;
173
174     /* Video */
175     int i_aspect;
176
177     /* SPU */
178     uint32_t clut[16];
179 };
180
181 static int Control   ( demux_t *, int, va_list );
182 static int Demux     ( demux_t * );
183 static int DemuxBlock( demux_t *, uint8_t *, int );
184
185 static void DemuxTitles( demux_t *, int * );
186 static void ESNew( demux_t *, int, int );
187
188 static int  DvdReadSetArea  ( demux_t *, int, int, int );
189 static void DvdReadSeek     ( demux_t *, int );
190 static void DvdReadHandleDSI( demux_t *, uint8_t * );
191 static void DvdReadFindCell ( demux_t * );
192
193 /*****************************************************************************
194  * Open:
195  *****************************************************************************/
196 static int Open( vlc_object_t *p_this )
197 {
198     demux_t      *p_demux = (demux_t*)p_this;
199     demux_sys_t  *p_sys;
200     char         *psz_name;
201     char         *psz_dvdcss_env;
202     dvd_reader_t *p_dvdread;
203     ifo_handle_t *p_vmg_file;
204     vlc_value_t  val;
205
206     if( !p_demux->psz_path || !*p_demux->psz_path )
207     {
208         /* Only when selected */
209         if( !p_this->b_force ) return VLC_EGENERIC;
210
211         psz_name = var_CreateGetString( p_this, "dvd" );
212         if( !psz_name )
213         {
214             psz_name = strdup("");
215         }
216     }
217     else
218         psz_name = ToLocaleDup( p_demux->psz_path );
219
220 #ifdef WIN32
221     if( psz_name[0] && psz_name[1] == ':' &&
222         psz_name[2] == '\\' && psz_name[3] == '\0' ) psz_name[2] = '\0';
223 #endif
224
225     /* Override environment variable DVDCSS_METHOD with config option
226      * (FIXME: this creates a small memory leak) */
227     psz_dvdcss_env = config_GetPsz( p_demux, "dvdread-css-method" );
228     if( psz_dvdcss_env && *psz_dvdcss_env )
229     {
230         char *psz_env;
231
232         psz_env = malloc( strlen("DVDCSS_METHOD=") +
233                           strlen( psz_dvdcss_env ) + 1 );
234         if( !psz_env )
235         {
236             free( psz_dvdcss_env );
237             return VLC_ENOMEM;
238         }
239
240         sprintf( psz_env, "%s%s", "DVDCSS_METHOD=", psz_dvdcss_env );
241
242         putenv( psz_env );
243     }
244     free( psz_dvdcss_env );
245
246     /* Open dvdread */
247     if( !(p_dvdread = DVDOpen( psz_name )) )
248     {
249         msg_Err( p_demux, "DVDRead cannot open source: %s", psz_name );
250         intf_UserFatal( p_demux, false, _("Playback failure"),
251                         _("DVDRead could not open the disk \"%s\"."), psz_name );
252         free( psz_name );
253         return VLC_EGENERIC;
254     }
255     free( psz_name );
256
257     /* Ifo allocation & initialisation */
258     if( !( p_vmg_file = ifoOpen( p_dvdread, 0 ) ) )
259     {
260         msg_Warn( p_demux, "cannot open VMG info" );
261         return VLC_EGENERIC;
262     }
263     msg_Dbg( p_demux, "VMG opened" );
264
265     /* Fill p_demux field */
266     DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;
267
268     ps_track_init( p_sys->tk );
269     p_sys->i_aspect = -1;
270     p_sys->i_title_cur_time = (mtime_t) 0;
271     p_sys->i_cell_cur_time = (mtime_t) 0;
272     p_sys->i_cell_duration = (mtime_t) 0;
273
274     p_sys->p_dvdread = p_dvdread;
275     p_sys->p_vmg_file = p_vmg_file;
276     p_sys->p_title = NULL;
277     p_sys->p_vts_file = NULL;
278
279     p_sys->i_title = p_sys->i_chapter = -1;
280     p_sys->i_mux_rate = 0;
281
282     var_Create( p_demux, "dvdread-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
283     var_Get( p_demux, "dvdread-angle", &val );
284     p_sys->i_angle = val.i_int > 0 ? val.i_int : 1;
285
286     DemuxTitles( p_demux, &p_sys->i_angle );
287     if( DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle ) != VLC_SUCCESS )
288     {
289         Close( p_this );
290         msg_Err( p_demux, "DvdReadSetArea(0,0,%i) failed (can't decrypt DVD?)",
291                  p_sys->i_angle );
292         return VLC_EGENERIC;
293     }
294
295     /* Update default_pts to a suitable value for dvdread access */
296     var_Create( p_demux, "dvdread-caching",
297                 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
298
299     return VLC_SUCCESS;
300 }
301
302 /*****************************************************************************
303  * Close:
304  *****************************************************************************/
305 static void Close( vlc_object_t *p_this )
306 {
307     demux_t     *p_demux = (demux_t*)p_this;
308     demux_sys_t *p_sys = p_demux->p_sys;
309     int i;
310
311     for( i = 0; i < PS_TK_COUNT; i++ )
312     {
313         ps_track_t *tk = &p_sys->tk[i];
314         if( tk->b_seen )
315         {
316             es_format_Clean( &tk->fmt );
317             if( tk->es ) es_out_Del( p_demux->out, tk->es );
318         }
319     }
320
321     /* Close libdvdread */
322     if( p_sys->p_title ) DVDCloseFile( p_sys->p_title );
323     if( p_sys->p_vts_file ) ifoClose( p_sys->p_vts_file );
324     if( p_sys->p_vmg_file ) ifoClose( p_sys->p_vmg_file );
325     DVDClose( p_sys->p_dvdread );
326
327     free( p_sys );
328 }
329
330 static int64_t dvdtime_to_time( dvd_time_t *dtime, uint8_t still_time )
331 {
332 /* Macro to convert Binary Coded Decimal to Decimal */
333 #define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))
334
335     double f_fps, f_ms;
336     int64_t i_micro_second = 0;
337
338     if (still_time == 0 || still_time == 0xFF)
339     {
340         i_micro_second += (int64_t)(BCD2D(dtime->hour)) * 60 * 60 * 1000000;
341         i_micro_second += (int64_t)(BCD2D(dtime->minute)) * 60 * 1000000;
342         i_micro_second += (int64_t)(BCD2D(dtime->second)) * 1000000;
343
344         switch((dtime->frame_u & 0xc0) >> 6)
345         {
346         case 1:
347             f_fps = 25.0;
348             break;
349         case 3:
350             f_fps = 29.97;
351             break;
352         default:
353             f_fps = 2500.0;
354             break;
355         }
356         f_ms = BCD2D(dtime->frame_u&0x3f) * 1000.0 / f_fps;
357         i_micro_second += (int64_t)(f_ms * 1000.0);
358     }
359     else
360     {
361         i_micro_second = still_time;
362         i_micro_second = (int64_t)((double)i_micro_second * 1000000.0);
363     }
364
365     return i_micro_second;
366 }
367
368 /*****************************************************************************
369  * Control:
370  *****************************************************************************/
371 static int Control( demux_t *p_demux, int i_query, va_list args )
372 {
373     demux_sys_t *p_sys = p_demux->p_sys;
374     double f, *pf;
375     bool *pb;
376     int64_t *pi64;
377     input_title_t ***ppp_title;
378     int *pi_int;
379     int i;
380
381     switch( i_query )
382     {
383         case DEMUX_GET_POSITION:
384         {
385             pf = (double*) va_arg( args, double* );
386
387             if( p_sys->i_title_blocks > 0 )
388                 *pf = (double)p_sys->i_title_offset / p_sys->i_title_blocks;
389             else
390                 *pf = 0.0;
391
392             return VLC_SUCCESS;
393         }
394         case DEMUX_SET_POSITION:
395         {
396             f = (double)va_arg( args, double );
397
398             DvdReadSeek( p_demux, f * p_sys->i_title_blocks );
399
400             return VLC_SUCCESS;
401         }
402         case DEMUX_GET_TIME:
403             pi64 = (int64_t*)va_arg( args, int64_t * );
404             if( p_demux->info.i_title >= 0 && p_demux->info.i_title < p_sys->i_titles )
405             {
406                 *pi64 = (int64_t) dvdtime_to_time( &p_sys->p_cur_pgc->playback_time, 0 ) /
407                         p_sys->i_title_blocks * p_sys->i_title_offset;
408                 return VLC_SUCCESS;
409             }
410             *pi64 = 0;
411             return VLC_EGENERIC;
412
413         case DEMUX_GET_LENGTH:
414             pi64 = (int64_t*)va_arg( args, int64_t * );
415             if( p_demux->info.i_title >= 0 && p_demux->info.i_title < p_sys->i_titles )
416             {
417                 *pi64 = (int64_t)dvdtime_to_time( &p_sys->p_cur_pgc->playback_time, 0 );
418                 return VLC_SUCCESS;
419             }
420             *pi64 = 0;
421             return VLC_EGENERIC;
422
423         /* Special for access_demux */
424         case DEMUX_CAN_PAUSE:
425         case DEMUX_CAN_SEEK:
426         case DEMUX_CAN_CONTROL_PACE:
427             /* TODO */
428             pb = (bool*)va_arg( args, bool * );
429             *pb = true;
430             return VLC_SUCCESS;
431
432         case DEMUX_SET_PAUSE_STATE:
433             return VLC_SUCCESS;
434
435         case DEMUX_GET_TITLE_INFO:
436             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
437             pi_int    = (int*)va_arg( args, int* );
438             *((int*)va_arg( args, int* )) = 1; /* Title offset */
439             *((int*)va_arg( args, int* )) = 1; /* Chapter offset */
440
441             /* Duplicate title infos */
442             *pi_int = p_sys->i_titles;
443             *ppp_title = malloc( sizeof(input_title_t **) * p_sys->i_titles );
444             for( i = 0; i < p_sys->i_titles; i++ )
445             {
446                 (*ppp_title)[i] = vlc_input_title_Duplicate(p_sys->titles[i]);
447             }
448             return VLC_SUCCESS;
449
450         case DEMUX_SET_TITLE:
451             i = (int)va_arg( args, int );
452             if( DvdReadSetArea( p_demux, i, 0, -1 ) != VLC_SUCCESS )
453             {
454                 msg_Warn( p_demux, "cannot set title/chapter" );
455                 return VLC_EGENERIC;
456             }
457             p_demux->info.i_update |=
458                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
459             p_demux->info.i_title = i;
460             p_demux->info.i_seekpoint = 0;
461             return VLC_SUCCESS;
462
463         case DEMUX_SET_SEEKPOINT:
464             i = (int)va_arg( args, int );
465             if( DvdReadSetArea( p_demux, -1, i, -1 ) != VLC_SUCCESS )
466             {
467                 msg_Warn( p_demux, "cannot set title/chapter" );
468                 return VLC_EGENERIC;
469             }
470             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
471             p_demux->info.i_seekpoint = i;
472             return VLC_SUCCESS;
473
474         case DEMUX_GET_PTS_DELAY:
475             pi64 = (int64_t*)va_arg( args, int64_t * );
476             *pi64 = (int64_t)var_GetInteger( p_demux, "dvdread-caching" )*1000;
477             return VLC_SUCCESS;
478
479         /* TODO implement others */
480         default:
481             return VLC_EGENERIC;
482     }
483 }
484
485 /*****************************************************************************
486  * Demux:
487  *****************************************************************************/
488 static int Demux( demux_t *p_demux )
489 {
490     demux_sys_t *p_sys = p_demux->p_sys;
491
492     uint8_t p_buffer[DVD_VIDEO_LB_LEN * DVD_BLOCK_READ_ONCE];
493     int i_blocks_once, i_read;
494     int i;
495
496     /*
497      * Playback by cell in this pgc, starting at the cell for our chapter.
498      */
499
500     /*
501      * Check end of pack, and select the following one
502      */
503     if( !p_sys->i_pack_len )
504     {
505         /* Read NAV packet */
506         if( DVDReadBlocks( p_sys->p_title, p_sys->i_next_vobu,
507                            1, p_buffer ) != 1 )
508         {
509             msg_Err( p_demux, "read failed for block %d", p_sys->i_next_vobu );
510             intf_UserWarn( p_demux, _("Playback failure"),
511                             _("DVDRead could not read block %d."),
512                            p_sys->i_next_vobu );
513             return -1;
514         }
515
516         /* Basic check to be sure we don't have a empty title
517          * go to next title if so */
518         //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
519
520         /* Parse the contained dsi packet */
521         DvdReadHandleDSI( p_demux, p_buffer );
522
523         /* End of title */
524         if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells )
525         {
526             if( p_sys->i_title + 1 >= p_sys->i_titles )
527             {
528                 return 0; /* EOF */
529             }
530
531             DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
532         }
533
534         if( p_sys->i_pack_len >= 1024 )
535         {
536             msg_Err( p_demux, "i_pack_len >= 1024 (%i). "
537                      "This shouldn't happen!", p_sys->i_pack_len );
538             return 0; /* EOF */
539         }
540
541         /* FIXME: Ugly kludge: we send the pack block to the input for it
542          * sometimes has a zero scr and restart the sync */
543         p_sys->i_cur_block++;
544         p_sys->i_title_offset++;
545
546         DemuxBlock( p_demux, p_buffer, DVD_VIDEO_LB_LEN );
547     }
548
549     if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells )
550     {
551         if( p_sys->i_title + 1 >= p_sys->i_titles )
552         {
553             return 0; /* EOF */
554         }
555
556         DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
557     }
558
559     /*
560      * Read actual data
561      */
562     i_blocks_once = __MIN( p_sys->i_pack_len, DVD_BLOCK_READ_ONCE );
563     p_sys->i_pack_len -= i_blocks_once;
564
565     /* Reads from DVD */
566     i_read = DVDReadBlocks( p_sys->p_title, p_sys->i_cur_block,
567                             i_blocks_once, p_buffer );
568     if( i_read != i_blocks_once )
569     {
570         msg_Err( p_demux, "read failed for %d/%d blocks at 0x%02x",
571                  i_read, i_blocks_once, p_sys->i_cur_block );
572         intf_UserFatal( p_demux, false, _("Playback failure"),
573                         _("DVDRead could not read %d/%d blocks at 0x%02x."),
574                         i_read, i_blocks_once, p_sys->i_cur_block );
575         return -1;
576     }
577
578     p_sys->i_cur_block += i_read;
579     p_sys->i_title_offset += i_read;
580
581 #if 0
582     msg_Dbg( p_demux, "i_blocks: %d len: %d current: 0x%02x",
583              i_read, p_sys->i_pack_len, p_sys->i_cur_block );
584 #endif
585
586     for( i = 0; i < i_read; i++ )
587     {
588         DemuxBlock( p_demux, p_buffer + i * DVD_VIDEO_LB_LEN,
589                     DVD_VIDEO_LB_LEN );
590     }
591
592 #undef p_pgc
593
594     return 1;
595 }
596
597 /*****************************************************************************
598  * DemuxBlock: demux a given block
599  *****************************************************************************/
600 static int DemuxBlock( demux_t *p_demux, uint8_t *pkt, int i_pkt )
601 {
602     demux_sys_t *p_sys = p_demux->p_sys;
603     uint8_t     *p = pkt;
604
605     while( p < &pkt[i_pkt] )
606     {
607         int i_size = ps_pkt_size( p, &pkt[i_pkt] - p );
608         block_t *p_pkt;
609         if( i_size <= 0 )
610         {
611             break;
612         }
613
614         /* Create a block */
615         p_pkt = block_New( p_demux, i_size );
616         memcpy( p_pkt->p_buffer, p, i_size);
617
618         /* Parse it and send it */
619         switch( 0x100 | p[3] )
620         {
621         case 0x1b9:
622         case 0x1bb:
623         case 0x1bc:
624
625 #ifdef DVDREAD_DEBUG
626             if( p[3] == 0xbc )
627             {
628                 msg_Warn( p_demux, "received a PSM packet" );
629             }
630             else if( p[3] == 0xbb )
631             {
632                 msg_Warn( p_demux, "received a SYSTEM packet" );
633             }
634 #endif
635             block_Release( p_pkt );
636             break;
637
638         case 0x1ba:
639         {
640             int64_t i_scr;
641             int i_mux_rate;
642             if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) )
643             {
644                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr );
645                 if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
646             }
647             block_Release( p_pkt );
648             break;
649         }
650         default:
651         {
652             int i_id = ps_pkt_id( p_pkt );
653             if( i_id >= 0xc0 )
654             {
655                 ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
656
657                 if( !tk->b_seen )
658                 {
659                     ESNew( p_demux, i_id, 0 );
660                 }
661                 if( tk->b_seen && tk->es &&
662                     !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
663                 {
664                     es_out_Send( p_demux->out, tk->es, p_pkt );
665                 }
666                 else
667                 {
668                     block_Release( p_pkt );
669                 }
670             }
671             else
672             {
673                 block_Release( p_pkt );
674             }
675             break;
676         }
677         }
678
679         p += i_size;
680     }
681
682     return VLC_SUCCESS;
683 }
684
685 /*****************************************************************************
686  * ESNew: register a new elementary stream
687  *****************************************************************************/
688 static void ESNew( demux_t *p_demux, int i_id, int i_lang )
689 {
690     demux_sys_t *p_sys = p_demux->p_sys;
691     ps_track_t  *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
692     char psz_language[3];
693
694     if( tk->b_seen ) return;
695
696     if( ps_track_fill( tk, 0, i_id ) )
697     {
698         msg_Warn( p_demux, "unknown codec for id=0x%x", i_id );
699         return;
700     }
701
702     psz_language[0] = psz_language[1] = psz_language[2] = 0;
703     if( i_lang && i_lang != 0xffff )
704     {
705         psz_language[0] = (i_lang >> 8)&0xff;
706         psz_language[1] = (i_lang     )&0xff;
707     }
708
709     /* Add a new ES */
710     if( tk->fmt.i_cat == VIDEO_ES )
711     {
712         if( p_sys->i_aspect >= 0 )
713         {
714             tk->fmt.video.i_aspect = p_sys->i_aspect;
715         }
716     }
717     else if( tk->fmt.i_cat == AUDIO_ES )
718     {
719         int i_audio = -1;
720         /* find the audio number PLEASE find another way */
721         if( (i_id&0xbdf8) == 0xbd88 )       /* dts */
722         {
723             i_audio = i_id&0x07;
724         }
725         else if( (i_id&0xbdf0) == 0xbd80 )  /* a52 */
726         {
727             i_audio = i_id&0xf;
728         }
729         else if( (i_id&0xbdf0) == 0xbda0 )  /* lpcm */
730         {
731             i_audio = i_id&0x1f;
732         }
733         else if( ( i_id&0xe0 ) == 0xc0 )    /* mpga */
734         {
735             i_audio = i_id&0x1f;
736         }
737
738         if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
739     }
740     else if( tk->fmt.i_cat == SPU_ES )
741     {
742         /* Palette */
743         tk->fmt.subs.spu.palette[0] = 0xBeef;
744         memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut,
745                 16 * sizeof( uint32_t ) );
746
747         if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
748     }
749
750     tk->es = es_out_Add( p_demux->out, &tk->fmt );
751     tk->b_seen = true;
752 }
753
754 /*****************************************************************************
755  * DvdReadSetArea: initialize input data for title x, chapter y.
756  * It should be called for each user navigation request.
757  *****************************************************************************
758  * Take care that i_title and i_chapter start from 0.
759  *****************************************************************************/
760 static int DvdReadSetArea( demux_t *p_demux, int i_title, int i_chapter,
761                            int i_angle )
762 {
763     demux_sys_t *p_sys = p_demux->p_sys;
764     int pgc_id = 0, pgn = 0;
765     int i;
766
767 #define p_pgc p_sys->p_cur_pgc
768 #define p_vmg p_sys->p_vmg_file
769 #define p_vts p_sys->p_vts_file
770
771     if( i_title >= 0 && i_title < p_sys->i_titles &&
772         i_title != p_sys->i_title )
773     {
774         int i_start_cell, i_end_cell;
775
776         if( p_sys->p_title != NULL ) DVDCloseFile( p_sys->p_title );
777         if( p_vts != NULL ) ifoClose( p_vts );
778         p_sys->i_title = i_title;
779
780         /*
781          *  We have to load all title information
782          */
783         msg_Dbg( p_demux, "open VTS %d, for title %d",
784                  p_vmg->tt_srpt->title[i_title].title_set_nr, i_title + 1 );
785
786         /* Ifo vts */
787         if( !( p_vts = ifoOpen( p_sys->p_dvdread,
788                p_vmg->tt_srpt->title[i_title].title_set_nr ) ) )
789         {
790             msg_Err( p_demux, "fatal error in vts ifo" );
791             return VLC_EGENERIC;
792         }
793
794         /* Title position inside the selected vts */
795         p_sys->i_ttn = p_vmg->tt_srpt->title[i_title].vts_ttn;
796
797         /* Find title start/end */
798         pgc_id = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgcn;
799         pgn = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgn;
800         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
801
802         p_sys->i_title_start_cell =
803             i_start_cell = p_pgc->program_map[pgn - 1] - 1;
804         p_sys->i_title_start_block =
805             p_pgc->cell_playback[i_start_cell].first_sector;
806
807         p_sys->i_title_end_cell =
808             i_end_cell = p_pgc->nr_of_cells - 1;
809         p_sys->i_title_end_block =
810             p_pgc->cell_playback[i_end_cell].last_sector;
811
812         p_sys->i_title_offset = 0;
813
814         p_sys->i_title_blocks = 0;
815         for( i = i_start_cell; i <= i_end_cell; i++ )
816         {
817             p_sys->i_title_blocks += p_pgc->cell_playback[i].last_sector -
818                 p_pgc->cell_playback[i].first_sector + 1;
819         }
820
821         msg_Dbg( p_demux, "title %d vts_title %d pgc %d pgn %d "
822                  "start %d end %d blocks: %d",
823                  i_title + 1, p_sys->i_ttn, pgc_id, pgn,
824                  p_sys->i_title_start_block, p_sys->i_title_end_block,
825                  p_sys->i_title_blocks );
826
827         /*
828          * Set properties for current chapter
829          */
830         p_sys->i_chapter = 0;
831         p_sys->i_chapters =
832             p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].nr_of_ptts;
833
834         pgc_id = p_vts->vts_ptt_srpt->title[
835                     p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgcn;
836         pgn = p_vts->vts_ptt_srpt->title[
837                     p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgn;
838
839         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
840         p_sys->i_pack_len = 0;
841         p_sys->i_next_cell =
842             p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
843         DvdReadFindCell( p_demux );
844
845         p_sys->i_next_vobu = p_sys->i_cur_block =
846             p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
847
848         /*
849          * Angle management
850          */
851         p_sys->i_angles = p_vmg->tt_srpt->title[i_title].nr_of_angles;
852         if( p_sys->i_angle > p_sys->i_angles ) p_sys->i_angle = 1;
853
854         /*
855          * We've got enough info, time to open the title set data.
856          */
857         if( !( p_sys->p_title = DVDOpenFile( p_sys->p_dvdread,
858             p_vmg->tt_srpt->title[i_title].title_set_nr,
859             DVD_READ_TITLE_VOBS ) ) )
860         {
861             msg_Err( p_demux, "cannot open title (VTS_%02d_1.VOB)",
862                      p_vmg->tt_srpt->title[i_title].title_set_nr );
863             return VLC_EGENERIC;
864         }
865
866         //IfoPrintTitle( p_demux );
867
868         /*
869          * Destroy obsolete ES by reinitializing program 0
870          * and find all ES in title with ifo data
871          */
872         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
873
874         for( i = 0; i < PS_TK_COUNT; i++ )
875         {
876             ps_track_t *tk = &p_sys->tk[i];
877             if( tk->b_seen )
878             {
879                 es_format_Clean( &tk->fmt );
880                 if( tk->es ) es_out_Del( p_demux->out, tk->es );
881             }
882             tk->b_seen = false;
883         }
884
885         if( p_demux->info.i_title != i_title )
886         {
887             p_demux->info.i_update |=
888                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
889             p_demux->info.i_title = i_title;
890             p_demux->info.i_seekpoint = 0;
891         }
892
893         /* TODO: re-add angles */
894
895
896         ESNew( p_demux, 0xe0, 0 ); /* Video, FIXME ? */
897         p_sys->i_aspect = p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio;
898
899 #define audio_control \
900     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
901
902         /* Audio ES, in the order they appear in the .ifo */
903         for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams; i++ )
904         {
905             int i_position = 0;
906             uint16_t i_id;
907
908             //IfoPrintAudio( p_demux, i );
909
910             /* Audio channel is active if first byte is 0x80 */
911             if( audio_control & 0x8000 )
912             {
913                 i_position = ( audio_control & 0x7F00 ) >> 8;
914
915                 msg_Dbg( p_demux, "audio position  %d", i_position );
916                 switch( p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format )
917                 {
918                 case 0x00: /* A52 */
919                     i_id = (0x80 + i_position) | 0xbd00;
920                     break;
921                 case 0x02:
922                 case 0x03: /* MPEG audio */
923                     i_id = 0xc000 + i_position;
924                     break;
925                 case 0x04: /* LPCM */
926                     i_id = (0xa0 + i_position) | 0xbd00;
927                     break;
928                 case 0x06: /* DTS */
929                     i_id = (0x88 + i_position) | 0xbd00;
930                     break;
931                 default:
932                     i_id = 0;
933                     msg_Err( p_demux, "unknown audio type %.2x",
934                         p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format );
935                 }
936
937                 ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
938                        vts_audio_attr[i - 1].lang_code );
939             }
940         }
941 #undef audio_control
942
943 #define spu_palette \
944     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->palette
945
946         memcpy( p_sys->clut, spu_palette, 16 * sizeof( uint32_t ) );
947
948 #define spu_control \
949     p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i-1]
950
951         /* Sub Picture ES */
952         for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
953         {
954             int i_position = 0;
955             uint16_t i_id;
956
957             //IfoPrintSpu( p_sys, i );
958             msg_Dbg( p_demux, "spu %d 0x%02x", i, spu_control );
959
960             if( spu_control & 0x80000000 )
961             {
962                 /*  there are several streams for one spu */
963                 if( p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
964                 {
965                     /* 16:9 */
966                     switch( p_vts->vtsi_mat->vts_video_attr.permitted_df )
967                     {
968                     case 1: /* letterbox */
969                         i_position = spu_control & 0xff;
970                         break;
971                     case 2: /* pan&scan */
972                         i_position = ( spu_control >> 8 ) & 0xff;
973                         break;
974                     default: /* widescreen */
975                         i_position = ( spu_control >> 16 ) & 0xff;
976                         break;
977                     }
978                 }
979                 else
980                 {
981                     /* 4:3 */
982                     i_position = ( spu_control >> 24 ) & 0x7F;
983                 }
984
985                 i_id = (0x20 + i_position) | 0xbd00;
986
987                 ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
988                        vts_subp_attr[i - 1].lang_code );
989             }
990         }
991 #undef spu_control
992
993     }
994     else if( i_title != -1 && i_title != p_sys->i_title )
995
996     {
997         return VLC_EGENERIC; /* Couldn't set title */
998     }
999
1000     /*
1001      * Chapter selection
1002      */
1003
1004     if( i_chapter >= 0 && i_chapter < p_sys->i_chapters )
1005     {
1006         pgc_id = p_vts->vts_ptt_srpt->title[
1007                      p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
1008         pgn = p_vts->vts_ptt_srpt->title[
1009                   p_sys->i_ttn - 1].ptt[i_chapter].pgn;
1010
1011         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
1012
1013         p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
1014         p_sys->i_chapter = i_chapter;
1015         DvdReadFindCell( p_demux );
1016
1017         p_sys->i_title_offset = 0;
1018         for( i = p_sys->i_title_start_cell; i < p_sys->i_cur_cell; i++ )
1019         {
1020             p_sys->i_title_offset += p_pgc->cell_playback[i].last_sector -
1021                 p_pgc->cell_playback[i].first_sector + 1;
1022         }
1023
1024         p_sys->i_pack_len = 0;
1025         p_sys->i_next_vobu = p_sys->i_cur_block =
1026             p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
1027
1028         if( p_demux->info.i_seekpoint != i_chapter )
1029         {
1030             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
1031             p_demux->info.i_seekpoint = i_chapter;
1032         }
1033     }
1034     else if( i_chapter != -1 )
1035
1036     {
1037         return VLC_EGENERIC; /* Couldn't set chapter */
1038     }
1039
1040 #undef p_pgc
1041 #undef p_vts
1042 #undef p_vmg
1043
1044     return VLC_SUCCESS;
1045 }
1046
1047 /*****************************************************************************
1048  * DvdReadSeek : Goes to a given position on the stream.
1049  *****************************************************************************
1050  * This one is used by the input and translate chronological position from
1051  * input to logical position on the device.
1052  *****************************************************************************/
1053 static void DvdReadSeek( demux_t *p_demux, int i_block_offset )
1054 {
1055     demux_sys_t *p_sys = p_demux->p_sys;
1056     int i_chapter = 0;
1057     int i_cell = 0;
1058     int i_vobu = 0;
1059     int i_sub_cell = 0;
1060     int i_block;
1061
1062 #define p_pgc p_sys->p_cur_pgc
1063 #define p_vts p_sys->p_vts_file
1064
1065     /* Find cell */
1066     i_block = i_block_offset;
1067     for( i_cell = p_sys->i_title_start_cell;
1068          i_cell <= p_sys->i_title_end_cell; i_cell++ )
1069     {
1070         if( i_block < (int)p_pgc->cell_playback[i_cell].last_sector -
1071             (int)p_pgc->cell_playback[i_cell].first_sector + 1 ) break;
1072
1073         i_block -= (p_pgc->cell_playback[i_cell].last_sector -
1074             p_pgc->cell_playback[i_cell].first_sector + 1);
1075     }
1076     if( i_cell > p_sys->i_title_end_cell )
1077     {
1078         msg_Err( p_demux, "couldn't find cell for block %i", i_block_offset );
1079         return;
1080     }
1081     i_block += p_pgc->cell_playback[i_cell].first_sector;
1082     p_sys->i_title_offset = i_block_offset;
1083
1084     /* Find chapter */
1085     for( i_chapter = 0; i_chapter < p_sys->i_chapters; i_chapter++ )
1086     {
1087         int pgc_id, pgn, i_tmp;
1088
1089         pgc_id = p_vts->vts_ptt_srpt->title[
1090                     p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
1091         pgn = p_vts->vts_ptt_srpt->title[
1092                     p_sys->i_ttn - 1].ptt[i_chapter].pgn;
1093
1094         i_tmp = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc->program_map[pgn-1];
1095
1096         if( i_tmp > i_cell ) break;
1097     }
1098
1099     if( i_chapter < p_sys->i_chapters &&
1100         p_demux->info.i_seekpoint != i_chapter )
1101     {
1102         p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
1103         p_demux->info.i_seekpoint = i_chapter;
1104     }
1105
1106     /* Find vobu */
1107     while( (int)p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu] <= i_block )
1108     {
1109         i_vobu++;
1110     }
1111
1112     /* Find sub_cell */
1113     while( p_vts->vts_c_adt->cell_adr_table[i_sub_cell].start_sector <
1114            p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu-1] )
1115     {
1116         i_sub_cell++;
1117     }
1118
1119 #if 1
1120     msg_Dbg( p_demux, "cell %d i_sub_cell %d chapter %d vobu %d "
1121              "cell_sector %d vobu_sector %d sub_cell_sector %d",
1122              i_cell, i_sub_cell, i_chapter, i_vobu,
1123              p_sys->p_cur_pgc->cell_playback[i_cell].first_sector,
1124              p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu],
1125              p_vts->vts_c_adt->cell_adr_table[i_sub_cell - 1].start_sector);
1126 #endif
1127
1128     p_sys->i_cur_block = i_block;
1129     p_sys->i_next_vobu = p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu];
1130     p_sys->i_pack_len = p_sys->i_next_vobu - i_block;
1131     p_sys->i_cur_cell = i_cell;
1132     p_sys->i_chapter = i_chapter;
1133     DvdReadFindCell( p_demux );
1134
1135 #undef p_vts
1136 #undef p_pgc
1137
1138     return;
1139 }
1140
1141 /*****************************************************************************
1142  * DvdReadHandleDSI
1143  *****************************************************************************/
1144 static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
1145 {
1146     demux_sys_t *p_sys = p_demux->p_sys;
1147
1148     navRead_DSI( &p_sys->dsi_pack, &p_data[DSI_START_BYTE] );
1149
1150     /*
1151      * Determine where we go next.  These values are the ones we mostly
1152      * care about.
1153      */
1154     p_sys->i_cur_block = p_sys->dsi_pack.dsi_gi.nv_pck_lbn;
1155     p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
1156
1157     /*
1158      * Store the timecodes so we can get the current time
1159      */
1160     p_sys->i_title_cur_time = (mtime_t) (p_sys->dsi_pack.dsi_gi.nv_pck_scr / 90 * 1000);
1161     p_sys->i_cell_cur_time = (mtime_t) dvdtime_to_time( &p_sys->dsi_pack.dsi_gi.c_eltm, 0 );
1162
1163     /*
1164      * If we're not at the end of this cell, we can determine the next
1165      * VOBU to display using the VOBU_SRI information section of the
1166      * DSI.  Using this value correctly follows the current angle,
1167      * avoiding the doubled scenes in The Matrix, and makes our life
1168      * really happy.
1169      */
1170
1171     p_sys->i_next_vobu = p_sys->i_cur_block +
1172         ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
1173
1174     if( p_sys->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL
1175         && p_sys->i_angle > 1 )
1176     {
1177         switch( ( p_sys->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
1178         {
1179         case 0x4:
1180             /* Interleaved unit with no angle */
1181             if( p_sys->dsi_pack.sml_pbi.ilvu_sa != 0 )
1182             {
1183                 p_sys->i_next_vobu = p_sys->i_cur_block +
1184                     p_sys->dsi_pack.sml_pbi.ilvu_sa;
1185                 p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
1186             }
1187             else
1188             {
1189                 p_sys->i_next_vobu = p_sys->i_cur_block +
1190                     p_sys->dsi_pack.dsi_gi.vobu_ea + 1;
1191             }
1192             break;
1193         case 0x5:
1194             /* vobu is end of ilvu */
1195             if( p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address )
1196             {
1197                 p_sys->i_next_vobu = p_sys->i_cur_block +
1198                     p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address;
1199                 p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
1200
1201                 break;
1202             }
1203         case 0x6:
1204             /* vobu is beginning of ilvu */
1205         case 0x9:
1206             /* next scr is 0 */
1207         case 0xa:
1208             /* entering interleaved section */
1209         case 0x8:
1210             /* non interleaved cells in interleaved section */
1211         default:
1212             p_sys->i_next_vobu = p_sys->i_cur_block +
1213                 ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
1214             break;
1215         }
1216     }
1217     else if( p_sys->dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL )
1218     {
1219         p_sys->i_cur_cell = p_sys->i_next_cell;
1220
1221         /* End of title */
1222         if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells ) return;
1223
1224         DvdReadFindCell( p_demux );
1225
1226         p_sys->i_next_vobu =
1227             p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
1228
1229         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 );
1230     }
1231
1232
1233 #if 0
1234     msg_Dbg( p_demux, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d c_time %lld",
1235              p_sys->dsi_pack.dsi_gi.nv_pck_scr,
1236              p_sys->dsi_pack.dsi_gi.nv_pck_lbn,
1237              p_sys->dsi_pack.dsi_gi.vobu_ea,
1238              p_sys->dsi_pack.dsi_gi.vobu_vob_idn,
1239              p_sys->dsi_pack.dsi_gi.vobu_c_idn,
1240              dvdtime_to_time( &p_sys->dsi_pack.dsi_gi.c_eltm, 0 ) );
1241
1242     msg_Dbg( p_demux, "cell duration: %lld",
1243              (mtime_t)dvdtime_to_time( &p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].playback_time, 0 ) );
1244
1245     msg_Dbg( p_demux, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
1246              p_sys->dsi_pack.sml_pbi.category,
1247              p_sys->dsi_pack.sml_pbi.ilvu_ea,
1248              p_sys->dsi_pack.sml_pbi.ilvu_sa,
1249              p_sys->dsi_pack.sml_pbi.size );
1250
1251     msg_Dbg( p_demux, "next_vobu %d next_ilvu1 %d next_ilvu2 %d",
1252              p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff,
1253              p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle - 1 ].address,
1254              p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle ].address);
1255 #endif
1256 }
1257
1258 /*****************************************************************************
1259  * DvdReadFindCell
1260  *****************************************************************************/
1261 static void DvdReadFindCell( demux_t *p_demux )
1262 {
1263     demux_sys_t *p_sys = p_demux->p_sys;
1264
1265     pgc_t *p_pgc;
1266     int   pgc_id, pgn;
1267     int   i = 0;
1268
1269 #define cell p_sys->p_cur_pgc->cell_playback
1270
1271     if( cell[p_sys->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
1272     {
1273         p_sys->i_cur_cell += p_sys->i_angle - 1;
1274
1275         while( cell[p_sys->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL )
1276         {
1277             i++;
1278         }
1279         p_sys->i_next_cell = p_sys->i_cur_cell + i + 1;
1280     }
1281     else
1282     {
1283         p_sys->i_next_cell = p_sys->i_cur_cell + 1;
1284     }
1285
1286 #undef cell
1287
1288     if( p_sys->i_chapter + 1 >= p_sys->i_chapters ) return;
1289
1290     pgc_id = p_sys->p_vts_file->vts_ptt_srpt->title[
1291                 p_sys->i_ttn - 1].ptt[p_sys->i_chapter + 1].pgcn;
1292     pgn = p_sys->p_vts_file->vts_ptt_srpt->title[
1293               p_sys->i_ttn - 1].ptt[p_sys->i_chapter + 1].pgn;
1294     p_pgc = p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
1295
1296     if( p_sys->i_cur_cell >= p_pgc->program_map[pgn - 1] - 1 )
1297     {
1298         p_sys->i_chapter++;
1299
1300         if( p_sys->i_chapter < p_sys->i_chapters &&
1301             p_demux->info.i_seekpoint != p_sys->i_chapter )
1302         {
1303             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
1304             p_demux->info.i_seekpoint = p_sys->i_chapter;
1305         }
1306     }
1307 }
1308
1309 /*****************************************************************************
1310  * DemuxTitles: get the titles/chapters structure
1311  *****************************************************************************/
1312 static void DemuxTitles( demux_t *p_demux, int *pi_angle )
1313 {
1314     demux_sys_t *p_sys = p_demux->p_sys;
1315     input_title_t *t;
1316     seekpoint_t *s;
1317     int32_t i_titles;
1318     int i;
1319
1320     /* Find out number of titles/chapters */
1321 #define tt_srpt p_sys->p_vmg_file->tt_srpt
1322
1323     i_titles = tt_srpt->nr_of_srpts;
1324     msg_Dbg( p_demux, "number of titles: %d", i_titles );
1325
1326     for( i = 0; i < i_titles; i++ )
1327     {
1328         int32_t i_chapters = 0;
1329         int j;
1330
1331         i_chapters = tt_srpt->title[i].nr_of_ptts;
1332         msg_Dbg( p_demux, "title %d has %d chapters", i, i_chapters );
1333
1334         t = vlc_input_title_New();
1335
1336         for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
1337         {
1338             s = vlc_seekpoint_New();
1339             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1340         }
1341
1342         TAB_APPEND( p_sys->i_titles, p_sys->titles, t );
1343     }
1344
1345 #undef tt_srpt
1346 }