dvd_ifo.c 65.3 KB
Newer Older
Stéphane Borel's avatar
Stéphane Borel committed
1 2 3 4
/*****************************************************************************
 * dvd_ifo.c: Functions for ifo parsing
 *****************************************************************************
 * Copyright (C) 1999-2001 VideoLAN
5
 * $Id: dvd_ifo.c,v 1.20 2001/04/13 05:36:12 stef Exp $
Stéphane Borel's avatar
Stéphane Borel committed
6 7 8
 *
 * Author: Stphane Borel <stef@via.ecp.fr>
 *
9 10 11 12 13
 * based on:
 *  - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at>
 *  - IFO structure documentation by Thomas Mirlacher, Bjrn Englund,
 *  Hkan Hjort
 *
Stéphane Borel's avatar
Stéphane Borel committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
32 33 34
#include "defs.h"
#include "config.h"

Stéphane Borel's avatar
Stéphane Borel committed
35
#include <stdio.h>
36
#include <stdlib.h>
Stéphane Borel's avatar
Stéphane Borel committed
37 38 39 40 41 42 43 44
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

#include "common.h"

#include "intf_msg.h"
#include "dvd_ifo.h"
45
#include "dvd_udf.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
46
#include "dvd_css.h"
47
#include "input_dvd.h"
Stéphane Borel's avatar
Stéphane Borel committed
48

Stéphane Borel's avatar
 
Stéphane Borel committed
49 50 51
/*
 * Local prototypes
 */
52
void            CommandRead     ( command_desc_t );
53
static int      ReadTitle       ( ifo_t * , title_t *, off_t );
54
static int      FreeTitle       ( title_t * );
55
static int      ReadUnitInf     ( ifo_t * , unit_inf_t *, off_t );
56
static int      FreeUnitInf     ( unit_inf_t * );
57
static int      ReadTitleUnit   ( ifo_t * , title_unit_t *, off_t );
58
static int      FreeTitleUnit   ( title_unit_t * );
59
static int      ReadVobuMap     ( ifo_t * , vobu_map_t *, off_t );
60
static int      FreeVobuMap     ( vobu_map_t * );
61
static int      ReadCellInf     ( ifo_t * , cell_inf_t *, off_t );
62 63
static int      FreeCellInf     ( cell_inf_t * );
static int      FreeTitleSet    ( vts_t * );
Stéphane Borel's avatar
Stéphane Borel committed
64

65 66 67 68 69 70 71 72
/*****************************************************************************
 * ReadByte and so
 *****************************************************************************/
static __inline__ u8* FillBuffer( ifo_t* p_ifo, u8* pi_buffer, off_t i_pos )
{
    memset( pi_buffer, 0, DVD_LB_SIZE );
    p_ifo->i_pos = lseek( p_ifo->i_fd, i_pos, SEEK_SET );
    read( p_ifo->i_fd, pi_buffer, DVD_LB_SIZE );
Stéphane Borel's avatar
Stéphane Borel committed
73

74 75
    return pi_buffer;
}
Stéphane Borel's avatar
Stéphane Borel committed
76

77
static __inline__ u8 ReadByte( ifo_t * p_ifo, u8* pi_buffer, u8** pp_current )
78 79
{
    u8      i_ret;
Stéphane Borel's avatar
Stéphane Borel committed
80

81 82 83 84 85 86
    if( *pp_current >= pi_buffer + DVD_LB_SIZE )
    {
        *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
    }

    i_ret = *(*pp_current)++;
Stéphane Borel's avatar
Stéphane Borel committed
87

88 89
    return i_ret;
}
Stéphane Borel's avatar
Stéphane Borel committed
90

91
static __inline__ u16 ReadWord( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current )
92 93 94
{
    u16     i_ret;

95 96 97 98 99 100 101
    if( *pp_current >= pi_buffer + DVD_LB_SIZE - 2 )
    {
        *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
    }

    i_ret = U16_AT(*pp_current);
    (*pp_current) += 2;
102 103 104 105

    return i_ret;
}

106 107
static __inline__ u32 ReadDouble( ifo_t * p_ifo, u8* pi_buffer,
                                  u8** pp_current )
108 109 110
{
    u32     i_ret;

111 112 113 114 115 116 117
    if( *pp_current >= pi_buffer + DVD_LB_SIZE - 4 )
    {
        *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
    }

    i_ret = U32_AT(*pp_current);
    (*pp_current) += 4;
118 119 120 121

    return i_ret;
}

122
static __inline__ u64 ReadQuad( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current )
123 124 125
{
    u64     i_ret;

126 127 128 129 130 131 132
    if( *pp_current >= pi_buffer + DVD_LB_SIZE - 8 )
    {
        *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
    }

    i_ret = U64_AT(*pp_current);
    (*pp_current) += 8;
133 134 135

    return i_ret;
}
Stéphane Borel's avatar
Stéphane Borel committed
136

137 138
static __inline__ void ReadBits( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current,
                                  u8* pi_dest, int i_nb )
139
{
140 141 142 143 144 145 146
    if( *pp_current >= pi_buffer + DVD_LB_SIZE - i_nb )
    {
        *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
    }

    memcpy( pi_dest, *pp_current, i_nb );
    *pp_current += i_nb;
147 148 149

    return;
}
150

151 152
static __inline__ void DumpBits( ifo_t* p_ifo, u8* pi_buffer,
                                 u8** pp_current, int i_nb )
153
{
154 155 156 157 158 159
    if( *pp_current >= pi_buffer + DVD_LB_SIZE - i_nb )
    {
        *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
    }

    *pp_current += i_nb;
160 161 162

    return;
}
163

Stéphane Borel's avatar
Stéphane Borel committed
164
/*
165
 * IFO Management.
Stéphane Borel's avatar
Stéphane Borel committed
166 167
 */
/*****************************************************************************
168 169
 * IfoCreate : Creates an ifo structure and prepares for parsing directly
 *             on DVD device
Stéphane Borel's avatar
Stéphane Borel committed
170
 *****************************************************************************/
171
int IfoCreate( thread_dvd_data_t * p_dvd )
172
{
173 174
    p_dvd->p_ifo = malloc( sizeof(ifo_t) );
    if( p_dvd->p_ifo == NULL )
175 176 177
    {
        intf_ErrMsg( "ifo error: unable to allocate memory. aborting" );
        return -1;
178 179
    }

180
    /* if we are here the dvd device has already been opened */
181 182 183 184 185 186 187 188 189 190
    p_dvd->p_ifo->i_fd = p_dvd->i_fd;

    return 0;
}

/*****************************************************************************
 * IfoInit : Reads information from the management table.
 *****************************************************************************/
int IfoInit( ifo_t * p_ifo )
{
191 192
    u8                  pi_buffer[DVD_LB_SIZE];
    u8*                 p_current;
193 194 195 196
    u64                 i_temp;
    u32                 i_lba;
    int                 i, j, k;
    off_t               i_start;
Stéphane Borel's avatar
Stéphane Borel committed
197

198
    /* find the start sector of video information on the dvd */
199
    i_lba = UDFFindFile( p_ifo->i_fd, "/VIDEO_TS/VIDEO_TS.IFO");
200 201 202

    p_ifo->i_off = (off_t)(i_lba) * DVD_LB_SIZE;

203
    p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off );
204
//i_start = p_ifo->i_pos;
205 206 207 208 209 210
    /*
     * read the video manager information table
     */
#define manager_inf     p_ifo->vmg.manager_inf
//fprintf( stderr, "VMGI\n" );

211
    ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.psz_id, 12 );
212
    manager_inf.psz_id[12] = '\0';
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    manager_inf.i_vmg_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 12 );
    manager_inf.i_vmg_inf_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 1 );
    manager_inf.i_spec_ver = ReadByte( p_ifo, pi_buffer, &p_current );
    manager_inf.i_cat = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_volume_nb = ReadWord( p_ifo, pi_buffer, &p_current );
    manager_inf.i_volume = ReadWord( p_ifo, pi_buffer, &p_current );
    manager_inf.i_disc_side = ReadByte( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 19 );
    manager_inf.i_title_set_nb = ReadWord( p_ifo, pi_buffer, &p_current );
    ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.ps_provider_id, 32 );
    manager_inf.i_pos_code = ReadQuad( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 24 );
    manager_inf.i_vmg_inf_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_first_play_title_start_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 56 );
    manager_inf.i_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_title_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_title_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_parental_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_vts_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_text_data_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 32 );
239
//    GETS( &manager_inf.video_atrt );
240 241 242
DumpBits( p_ifo, pi_buffer, &p_current, 2 );
    DumpBits( p_ifo, pi_buffer, &p_current, 1 );
    manager_inf.i_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
243 244
//fprintf( stderr, "vmgi audio nb : %d\n", manager_inf.i_audio_nb );
    for( i=0 ; i < 8 ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
245
    {
246
        i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
Stéphane Borel's avatar
Stéphane Borel committed
247
    }
248 249
    DumpBits( p_ifo, pi_buffer, &p_current, 17 );
    manager_inf.i_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
250
//fprintf( stderr, "vmgi subpic nb : %d\n", manager_inf.i_spu_nb );
251
    for( i=0 ; i < manager_inf.i_spu_nb ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
252
    {
253
        ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
254 255 256 257 258 259
        /* FIXME : take care of endianness */
    }

    /*
     * read first play title.
     */
260 261
    if( ReadTitle( p_ifo, &p_ifo->vmg.title, p_ifo->i_off +
                          manager_inf.i_first_play_title_start_byte ) < 0 )
Stéphane Borel's avatar
Stéphane Borel committed
262
    {
263
        return -1;
Stéphane Borel's avatar
Stéphane Borel committed
264 265
    }

266 267 268 269 270
    /*
     * fills the title information structure.
     */
#define title_inf       p_ifo->vmg.title_inf
    if( manager_inf.i_title_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
271
    {
272 273 274
        p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off +
                    manager_inf.i_title_inf_start_sector *DVD_LB_SIZE );
//fprintf( stderr, "title inf %lld\n", p_ifo->i_pos );
275
    
276
        title_inf.i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current );
277
//fprintf( stderr, "title_inf: TTU nb %d\n", title_inf.i_title_nb );
278 279
        DumpBits( p_ifo, pi_buffer, &p_current, 2 );
        title_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
280 281 282 283
    
        /* parsing of title attributes */
        title_inf.p_attr = malloc( title_inf.i_title_nb *sizeof(title_attr_t) );
        if( title_inf.p_attr == NULL )
Stéphane Borel's avatar
Stéphane Borel committed
284
        {
285 286
            intf_ErrMsg( "ifo error: out of memory in IfoInit" );
            return -1;
Stéphane Borel's avatar
Stéphane Borel committed
287
        }
288 289
    
        for( i = 0 ; i < title_inf.i_title_nb ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
290
        {
291 292 293 294 295 296 297
            title_inf.p_attr[i].i_play_type = ReadByte( p_ifo, pi_buffer, &p_current );
            title_inf.p_attr[i].i_angle_nb = ReadByte( p_ifo, pi_buffer, &p_current );
            title_inf.p_attr[i].i_chapter_nb = ReadWord( p_ifo, pi_buffer, &p_current );
            title_inf.p_attr[i].i_parental_id = ReadWord( p_ifo, pi_buffer, &p_current );
            title_inf.p_attr[i].i_title_set_num = ReadByte( p_ifo, pi_buffer, &p_current );
            title_inf.p_attr[i].i_title_num = ReadByte( p_ifo, pi_buffer, &p_current );
            title_inf.p_attr[i].i_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
298
//fprintf( stderr, "title_inf: %d %d %d\n",title_inf.p_attr[i].i_chapter_nb ,title_inf.p_attr[i].i_title_set_num,title_inf.p_attr[i].i_title_num );
Stéphane Borel's avatar
Stéphane Borel committed
299 300
        }
    }
301
    else
Stéphane Borel's avatar
Stéphane Borel committed
302
    {
303
        title_inf.p_attr = NULL;
Stéphane Borel's avatar
Stéphane Borel committed
304
    }
305 306 307 308 309 310
#undef title_inf

    /*
     * fills the title unit structure.
     */
    if( manager_inf.i_title_unit_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
311
    {
312 313
        if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit, p_ifo->i_off +
                    manager_inf.i_title_unit_start_sector *DVD_LB_SIZE ) < 0 )
Stéphane Borel's avatar
Stéphane Borel committed
314
        {
315
            return -1;
Stéphane Borel's avatar
Stéphane Borel committed
316 317
        }
    }
318 319 320 321 322 323

    /*
     * fills the structure about parental information.
     */
#define parental        p_ifo->vmg.parental_inf
    if( manager_inf.i_parental_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
324
    {
325 326
        p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off +
                    manager_inf.i_parental_inf_start_sector *DVD_LB_SIZE );
327 328 329 330
        i_start = p_ifo->i_pos;

//fprintf( stderr, "PTL\n" );
    
331 332 333
        parental.i_country_nb = ReadWord( p_ifo, pi_buffer, &p_current );
        parental.i_vts_nb = ReadWord( p_ifo, pi_buffer, &p_current );
        parental.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
334 335 336 337
        
        parental.p_parental_desc = malloc( parental.i_country_nb *
                                           sizeof(parental_desc_t) );
        if( parental.p_parental_desc == NULL )
Stéphane Borel's avatar
Stéphane Borel committed
338
        {
339 340
            intf_ErrMsg( "ifo error: out of memory in IfoInit" );
            return -1;
Stéphane Borel's avatar
Stéphane Borel committed
341
        }
342 343

        for( i = 0 ; i < parental.i_country_nb ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
344
        {
345
            ReadBits( p_ifo, pi_buffer, &p_current,
346
                      parental.p_parental_desc[i].ps_country_code, 2 );
347
            DumpBits( p_ifo, pi_buffer, &p_current, 2 );
348
            parental.p_parental_desc[i].i_parental_mask_start_byte =
349 350
                                                    ReadWord( p_ifo, pi_buffer, &p_current );
            DumpBits( p_ifo, pi_buffer, &p_current, 2 );
Stéphane Borel's avatar
Stéphane Borel committed
351
        }
352

353 354 355 356 357 358 359
        parental.p_parental_mask = malloc( parental.i_country_nb *
                                           sizeof(parental_mask_t) );
        if( parental.p_parental_mask == NULL )
        {
            intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
            return -1;
        }
360

361 362
        for( i = 0 ; i < parental.i_country_nb ; i++ )
        {
363 364
            p_current = FillBuffer( p_ifo, pi_buffer, i_start +
                      parental.p_parental_desc[i].i_parental_mask_start_byte );
365 366 367 368 369 370 371 372 373 374 375
            for( j = 0 ; j < 8 ; j++ )
            {
                parental.p_parental_mask[i].ppi_mask[j] =
                            malloc( ( parental.i_vts_nb + 1 ) *sizeof(u16) );
                if( parental.p_parental_mask[i].ppi_mask[j] == NULL )
                {
                    intf_ErrMsg( "ifo error: out of memory in IfoInit" );
                    return -1;
                }        
                for( k = 0 ; k < parental.i_vts_nb + 1 ; k++ )
                {
376
                    parental.p_parental_mask[i].ppi_mask[j][k] =
377
                                                        ReadWord( p_ifo, pi_buffer, &p_current );
378 379 380
                }
            }
        }
381
    }
382 383 384 385 386 387 388
#undef parental

    /*
     * information and attributes about for each vts.
     */
#define vts_inf     p_ifo->vmg.vts_inf
    if( manager_inf.i_vts_inf_start_sector )
389
    {
390
        u64             i_temp;
391

392 393
        p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off +
                        manager_inf.i_vts_inf_start_sector *DVD_LB_SIZE );
394 395 396 397
        i_start = p_ifo->i_pos;
    
//fprintf( stderr, "VTS ATTR\n" );
    
398
        vts_inf.i_vts_nb = ReadWord( p_ifo, pi_buffer, &p_current );;
399
//fprintf( stderr, "VTS ATTR Nb: %d\n", vts_inf.i_vts_nb );
400 401
        DumpBits( p_ifo, pi_buffer, &p_current, 2 );
        vts_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
402 403 404 405 406 407 408
        vts_inf.pi_vts_attr_start_byte =
                            malloc( vts_inf.i_vts_nb *sizeof(u32) );
        if( vts_inf.pi_vts_attr_start_byte == NULL )
        {
            intf_ErrMsg( "ifo error: out of memory in IfoInit" );
            return -1;
        }
409

410 411
        for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
        {
412
            vts_inf.pi_vts_attr_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
413
        }
Stéphane Borel's avatar
Stéphane Borel committed
414

415 416 417 418 419 420
        vts_inf.p_vts_attr = malloc( vts_inf.i_vts_nb *sizeof(vts_attr_t) );
        if( vts_inf.p_vts_attr == NULL )
        {
            intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
            return -1;
        }
Stéphane Borel's avatar
Stéphane Borel committed
421

422 423
        for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
        {
424 425
            p_current = FillBuffer( p_ifo, pi_buffer, i_start +
                                    vts_inf.pi_vts_attr_start_byte[i] );
426 427
            vts_inf.p_vts_attr[i].i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
            vts_inf.p_vts_attr[i].i_cat_app_type  = ReadDouble( p_ifo, pi_buffer, &p_current );
428
    //        GETS( &vts_inf.p_vts_attr[i].vts_menu_video_attr );
429 430 431
DumpBits( p_ifo, pi_buffer, &p_current, 2 );
            DumpBits( p_ifo, pi_buffer, &p_current, 1 );
            vts_inf.p_vts_attr[i].i_vts_menu_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
432
//fprintf( stderr, "m audio nb : %d\n", vts_inf.p_vts_attr[i].i_vts_menu_audio_nb );
433 434
            for( j = 0 ; j < 8 ; j++ )
            {
435
                i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );;
436
            }
437 438
            DumpBits( p_ifo, pi_buffer, &p_current, 17 );
            vts_inf.p_vts_attr[i].i_vts_menu_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
439
//fprintf( stderr, "m subp nb : %d\n", vts_inf.p_vts_attr[i].i_vts_menu_spu_nb );
440 441
            for( j = 0 ; j < 28 ; j++ )
            {
442
                ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
443 444
                /* FIXME : Fix endianness issue here */
            }
445
            DumpBits( p_ifo, pi_buffer, &p_current, 2 );
446
    //        GETS( &vts_inf.p_vts_attr[i].vtstt_video_vts_inf );
447 448
DumpBits( p_ifo, pi_buffer, &p_current, 2 );
            DumpBits( p_ifo, pi_buffer, &p_current, 1 );
449
            vts_inf.p_vts_attr[i].i_vts_title_audio_nb =
450
                                                ReadDouble( p_ifo, pi_buffer, &p_current );
451
//fprintf( stderr, "tt audio nb : %d\n", vts_inf.p_vts_attr[i].i_vts_title_audio_nb );
452 453
            for( j = 0 ; j < 8 ; j++ )
            {
454
                i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );;
455
            }
456 457
            DumpBits( p_ifo, pi_buffer, &p_current, 17 );
            vts_inf.p_vts_attr[i].i_vts_title_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
458
//fprintf( stderr, "tt subp nb : %d\n", vts_inf.p_vts_attr[i].i_vts_title_spu_nb );
459 460
            for( j=0 ; j<28/*vts_inf.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ )
            {
461
                ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
462 463 464
                /* FIXME : Fix endianness issue here */
            }
        }
Stéphane Borel's avatar
Stéphane Borel committed
465
    }
466 467 468 469 470 471
#undef vts_inf

    /*
     * global cell map.
     */
    if( manager_inf.i_cell_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
472
    {
473 474
        if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf, p_ifo->i_off +
                       manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE ) < 0 )
475 476 477
        {
            return -1;
        }
Stéphane Borel's avatar
Stéphane Borel committed
478
    }
479 480 481 482 483

    /*
     * global vob unit map.
     */
    if( manager_inf.i_vobu_map_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
484
    {
485 486
        if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map, p_ifo->i_off +
                       manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE ) < 0 )
487 488 489
        {
            return -1;
        }
Stéphane Borel's avatar
Stéphane Borel committed
490
    }
491
#undef manager_inf
Stéphane Borel's avatar
Stéphane Borel committed
492

493
    p_ifo->vts.b_initialized = 0;
Stéphane Borel's avatar
Stéphane Borel committed
494

495
    intf_WarnMsg( 1, "ifo info: vmg initialized" );
Stéphane Borel's avatar
Stéphane Borel committed
496

497
    return 0;
Stéphane Borel's avatar
Stéphane Borel committed
498 499 500
}

/*****************************************************************************
501
 * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure.
Stéphane Borel's avatar
Stéphane Borel committed
502
 *****************************************************************************/
503
int IfoTitleSet( ifo_t * p_ifo )
Stéphane Borel's avatar
Stéphane Borel committed
504
{
505 506
    u8          pi_buffer[DVD_LB_SIZE];
    u8 *        p_current;
507 508 509 510
    off_t       i_off;
    off_t       i_start;
    u64         i_temp;
    int         i, j;
Stéphane Borel's avatar
Stéphane Borel committed
511

512
    if( p_ifo->vts.b_initialized )
Stéphane Borel's avatar
Stéphane Borel committed
513
    {
514
        FreeTitleSet( &p_ifo->vts );
Stéphane Borel's avatar
Stéphane Borel committed
515 516
    }

517 518 519 520
    i_off =
    (off_t)( p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_start_sector )
                   * DVD_LB_SIZE
                   + p_ifo->i_off;
Stéphane Borel's avatar
Stéphane Borel committed
521

522
//fprintf(stderr, "offset: %lld\n" , i_off );
Stéphane Borel's avatar
Stéphane Borel committed
523

524
    p_current = FillBuffer( p_ifo, pi_buffer, i_off );
525
//i_start = p_ifo->i_pos;
526 527 528 529 530 531 532
    p_ifo->vts.i_pos = p_ifo->i_pos;

#define manager_inf p_ifo->vts.manager_inf
    /*
     * reads manager information
     */
//fprintf( stderr, "VTSI\n" );
Stéphane Borel's avatar
Stéphane Borel committed
533

534
    ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.psz_id , 12 );
535
    manager_inf.psz_id[12] = '\0';
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
    manager_inf.i_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 12 );
    manager_inf.i_inf_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 1 );
    manager_inf.i_spec_ver = ReadByte( p_ifo, pi_buffer, &p_current );
    manager_inf.i_cat = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 90 );
    manager_inf.i_inf_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 60 );
    manager_inf.i_menu_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_title_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_title_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_title_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_menu_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_time_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_menu_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_menu_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    manager_inf.i_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
    DumpBits( p_ifo, pi_buffer, &p_current, 24 );
556
//    GETS( &manager_inf.m_video_atrt );
557 558 559
DumpBits( p_ifo, pi_buffer, &p_current, 2 );
    DumpBits( p_ifo, pi_buffer, &p_current, 1 );
    manager_inf.i_menu_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
560
    for( i = 0 ; i < 8 ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
561
    {
562
        i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
Stéphane Borel's avatar
Stéphane Borel committed
563
    }
564 565
    DumpBits( p_ifo, pi_buffer, &p_current, 17 );
    manager_inf.i_menu_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
566
    for( i = 0 ; i < 28 ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
567
    {
568
        ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
Stéphane Borel's avatar
Stéphane Borel committed
569 570
        /* FIXME : take care of endianness */
    }
571
    DumpBits( p_ifo, pi_buffer, &p_current, 2 );
572
//    GETS( &manager_inf.video_atrt );
573 574 575
DumpBits( p_ifo, pi_buffer, &p_current, 2 );
    DumpBits( p_ifo, pi_buffer, &p_current, 1 );
    manager_inf.i_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
576
//fprintf( stderr, "vtsi audio nb : %d\n", manager_inf.i_audio_nb );
577
    for( i = 0 ; i < 8 ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
578
    {
579
        i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
580
//fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
Stéphane Borel's avatar
Stéphane Borel committed
581 582 583 584 585 586 587
        i_temp >>= 8;
        manager_inf.p_audio_attr[i].i_bar = i_temp & 0xff;
        i_temp >>= 8;
        manager_inf.p_audio_attr[i].i_caption = i_temp & 0xff;
        i_temp >>= 8;
        manager_inf.p_audio_attr[i].i_foo = i_temp & 0xff;
        i_temp >>= 8;
588 589 590
        manager_inf.p_audio_attr[i].i_lang_code = i_temp & 0xffff;
        i_temp >>= 16;
        manager_inf.p_audio_attr[i].i_num_channels = i_temp & 0x7;
Stéphane Borel's avatar
Stéphane Borel committed
591 592 593
        i_temp >>= 3;
        manager_inf.p_audio_attr[i].i_test = i_temp & 0x1;
        i_temp >>= 1;
594 595 596 597 598 599 600 601 602 603 604 605
        manager_inf.p_audio_attr[i].i_sample_freq = i_temp & 0x3;
        i_temp >>= 2;
        manager_inf.p_audio_attr[i].i_quantization = i_temp & 0x3;
        i_temp >>= 2;
        manager_inf.p_audio_attr[i].i_appl_mode = i_temp & 0x3;
        i_temp >>= 2;
        manager_inf.p_audio_attr[i].i_type = i_temp & 0x3;
        i_temp >>= 2;
        manager_inf.p_audio_attr[i].i_multichannel_extension = i_temp & 0x1;
        i_temp >>= 1;
        manager_inf.p_audio_attr[i].i_coding_mode = i_temp & 0x7;
    }
606 607
    DumpBits( p_ifo, pi_buffer, &p_current, 17 );
    manager_inf.i_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
608
//fprintf( stderr, "vtsi subpic nb : %d\n", manager_inf.i_spu_nb );
609
    for( i=0 ; i<manager_inf.i_spu_nb ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
610
    {
611
        ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
612 613 614 615 616 617 618
        i_temp = hton64( i_temp ) >> 16;
//fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
        manager_inf.p_spu_attr[i].i_caption = i_temp & 0xff;
        i_temp >>= 16;
        manager_inf.p_spu_attr[i].i_lang_code = i_temp & 0xffff;
        i_temp >>= 16;
        manager_inf.p_spu_attr[i].i_prefix = i_temp & 0xffff;
Stéphane Borel's avatar
Stéphane Borel committed
619
    }
620 621 622 623 624 625

    /*
     * reads title information: set of pointers to title
     */
#define title_inf p_ifo->vts.title_inf
    if( manager_inf.i_title_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
626
    {
627 628
        p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->vts.i_pos +
                        manager_inf.i_title_inf_start_sector *DVD_LB_SIZE );
629 630 631 632 633

        i_start = p_ifo->i_pos;
    
//fprintf( stderr, "VTS PTR\n" );
   
634
        title_inf.i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current );
635
//fprintf( stderr, "VTS title_inf nb: %d\n", title_inf.i_title_nb );
636 637
        DumpBits( p_ifo, pi_buffer, &p_current, 2 );
        title_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
638 639 640 641 642 643 644 645 646 647

        title_inf.pi_start_byte = malloc( title_inf.i_title_nb *sizeof(u32) );
        if( title_inf.pi_start_byte == NULL )
        {
            intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
            return -1;
        }

        for( i = 0 ; i < title_inf.i_title_nb ; i++ )
        {
648
            title_inf.pi_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
649 650 651 652 653 654 655 656 657 658 659 660 661
        }

        /* Parsing of tts */
        title_inf.p_title_start = malloc( title_inf.i_title_nb
                                         *sizeof(title_start_t) );
        if( title_inf.p_title_start == NULL )
        {
            intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
            return -1;
        }

        for( i = 0 ; i < title_inf.i_title_nb ; i++ )
        {
662 663
            p_current = FillBuffer( p_ifo, pi_buffer, i_start +
                            title_inf.pi_start_byte[i] );
664

665
            title_inf.p_title_start[i].i_program_chain_num =
666 667
                                                       ReadWord( p_ifo, pi_buffer, &p_current );
            title_inf.p_title_start[i].i_program_num = ReadWord( p_ifo, pi_buffer, &p_current );
668 669
//fprintf( stderr, "VTS %d title_inf Pgc: %d Prg: %d\n", i,title_inf.p_title_start[i].i_program_chain_num, title_inf.p_title_start[i].i_program_num );
        }
Stéphane Borel's avatar
Stéphane Borel committed
670
    }
671 672 673 674 675 676
#undef title_inf

    /*
     * menu unit information
     */
    if( manager_inf.i_menu_unit_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
677
    {
678 679
        if( ReadTitleUnit( p_ifo, &p_ifo->vts.menu_unit, p_ifo->vts.i_pos +
                     manager_inf.i_menu_unit_start_sector *DVD_LB_SIZE ) < 0 )
680 681 682
        {
            return -1;
        }
Stéphane Borel's avatar
Stéphane Borel committed
683
    }
684 685 686 687 688

    /*
     * title unit information
     */
    if( manager_inf.i_title_unit_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
689
    {
690 691
        if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit, p_ifo->vts.i_pos +
                    manager_inf.i_title_unit_start_sector *DVD_LB_SIZE  ) < 0 )
692 693 694 695 696 697 698 699 700 701 702
        {
            return -1;
        }
    }

    /*
     * time map inforamtion
     */
#define time_inf p_ifo->vts.time_inf
    if( manager_inf.i_time_inf_start_sector )
    {
703
        u8      pi_buffer[DVD_LB_SIZE];
704 705 706

        p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->vts.i_pos +
                        manager_inf.i_time_inf_start_sector *DVD_LB_SIZE );
707 708 709

//fprintf( stderr, "TMAP\n" );

710 711 712
        time_inf.i_nb = ReadWord( p_ifo, pi_buffer, &p_current );;
        DumpBits( p_ifo, pi_buffer, &p_current, 2 );
        time_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
713 714 715

        time_inf.pi_start_byte = malloc( time_inf.i_nb *sizeof(u32) );
        if( time_inf.pi_start_byte == NULL )
Stéphane Borel's avatar
Stéphane Borel committed
716
        {
717 718 719 720 721 722
            intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
            return -1;
        }

        for( i = 0 ; i < time_inf.i_nb ; i++ )
        {    
723
            time_inf.pi_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
724 725 726 727 728 729 730 731 732 733 734
        }

        time_inf.p_time_map = malloc( time_inf.i_nb *sizeof(time_map_t) );
        if( time_inf.p_time_map == NULL )
        {
            intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
            return -1;
        }

        for( i = 0 ; i < time_inf.i_nb ; i++ )
        {    
735 736 737
            time_inf.p_time_map[i].i_time_unit = ReadByte( p_ifo, pi_buffer, &p_current );
            DumpBits( p_ifo, pi_buffer, &p_current, 1 );
            time_inf.p_time_map[i].i_entry_nb = ReadWord( p_ifo, pi_buffer, &p_current );
738 739 740 741

            time_inf.p_time_map[i].pi_sector =
                     malloc( time_inf.p_time_map[i].i_entry_nb *sizeof(u32) );
            if( time_inf.p_time_map[i].pi_sector == NULL )
Stéphane Borel's avatar
Stéphane Borel committed
742
            {
743 744 745 746 747
                intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
                return -1;
            }

            for( j = 0 ; j < time_inf.p_time_map[i].i_entry_nb ; j++ )
Stéphane Borel's avatar
Stéphane Borel committed
748
            {
749
                time_inf.p_time_map[i].pi_sector[j] = ReadDouble( p_ifo, pi_buffer, &p_current );
Stéphane Borel's avatar
Stéphane Borel committed
750 751 752
            }
        }
    }
753 754 755 756
#undef time_inf

    if( manager_inf.i_menu_cell_inf_start_sector )
    {
757 758
        if( ReadCellInf( p_ifo, &p_ifo->vts.menu_cell_inf, p_ifo->vts.i_pos +
                 manager_inf.i_menu_cell_inf_start_sector *DVD_LB_SIZE ) < 0 )
759 760 761 762 763 764 765
        {
            return -1;
        }
    }

    if( manager_inf.i_menu_vobu_map_start_sector )
    {
766 767
        if( ReadVobuMap( p_ifo, &p_ifo->vts.menu_vobu_map, p_ifo->vts.i_pos +
                  manager_inf.i_menu_vobu_map_start_sector *DVD_LB_SIZE ) < 0 )
768 769 770 771 772 773 774
        {
            return -1;
        }
    }

    if( manager_inf.i_cell_inf_start_sector )
    {
775 776
        if( ReadCellInf( p_ifo, &p_ifo->vts.cell_inf, p_ifo->vts.i_pos +
                        manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE ) )
777 778 779 780 781 782 783
        {
            return -1;
        }
    }

    if( manager_inf.i_vobu_map_start_sector )
    {
784 785
        if( ReadVobuMap( p_ifo, &p_ifo->vts.vobu_map, p_ifo->vts.i_pos +
                        manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE ) )
786 787 788 789
        {
            return -1;
        }
    }
790
#undef manager_inf
791

792
    intf_WarnMsg( 2, "ifo info: vts %d initialized",
793 794 795 796 797
         p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_title_set_num );

    p_ifo->vts.b_initialized = 1;

    return 0;
Stéphane Borel's avatar
Stéphane Borel committed
798 799 800
}

/*****************************************************************************
801
 * FreeTitleSet : free all structures allocated by IfoTitleSet
Stéphane Borel's avatar
Stéphane Borel committed
802
 *****************************************************************************/
803
static int FreeTitleSet( vts_t * p_vts )
Stéphane Borel's avatar
Stéphane Borel committed
804
{
805
    int     i;
Stéphane Borel's avatar
Stéphane Borel committed
806

807 808 809 810
    if( p_vts->manager_inf.i_vobu_map_start_sector )
    {
        FreeVobuMap( &p_vts->vobu_map );
    }
Stéphane Borel's avatar
Stéphane Borel committed
811

812
    if( p_vts->manager_inf.i_cell_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
813
    {
814
        FreeCellInf( &p_vts->cell_inf );
Stéphane Borel's avatar
Stéphane Borel committed
815
    }
816 817

    if( p_vts->manager_inf.i_menu_vobu_map_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
818
    {
819
        FreeVobuMap( &p_vts->menu_vobu_map );
Stéphane Borel's avatar
Stéphane Borel committed
820
    }
821 822

    if( p_vts->manager_inf.i_menu_cell_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
823
    {
824
        FreeCellInf( &p_vts->menu_cell_inf );
Stéphane Borel's avatar
Stéphane Borel committed
825
    }
826 827

    if( p_vts->manager_inf.i_time_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
828
    {
829
        for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ )
Stéphane Borel's avatar
Stéphane Borel committed
830
        {
831
            free( p_vts->time_inf.p_time_map[i].pi_sector );
Stéphane Borel's avatar
Stéphane Borel committed
832
        }
833 834 835

        free( p_vts->time_inf.p_time_map );
        free( p_vts->time_inf.pi_start_byte );
Stéphane Borel's avatar
Stéphane Borel committed
836 837
    }

838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
    if( p_vts->manager_inf.i_title_unit_start_sector )
    {
        FreeUnitInf( &p_vts->title_unit );
    }

    if( p_vts->manager_inf.i_menu_unit_start_sector )
    {
        FreeTitleUnit( &p_vts->menu_unit );
    }

    if( p_vts->manager_inf.i_title_inf_start_sector )
    {
        free( p_vts->title_inf.pi_start_byte );
        free( p_vts->title_inf.p_title_start );
    }

    p_vts->b_initialized = 0;
    
    return 0;
Stéphane Borel's avatar
Stéphane Borel committed
857
}
858

Stéphane Borel's avatar
Stéphane Borel committed
859
/*****************************************************************************
860
 * IfoDestroy : Frees all the memory allocated to ifo structures
Stéphane Borel's avatar
Stéphane Borel committed
861
 *****************************************************************************/
862
void IfoDestroy( ifo_t * p_ifo )
Stéphane Borel's avatar
Stéphane Borel committed
863
{
864 865 866 867 868
    int     i, j;

    FreeTitleSet( &p_ifo->vts );

    if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
869
    {
870
        FreeVobuMap( &p_ifo->vmg.vobu_map );
Stéphane Borel's avatar
Stéphane Borel committed
871
    }
872 873

    if( p_ifo->vmg.manager_inf.i_cell_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
874
    {
875
        FreeCellInf( &p_ifo->vmg.cell_inf );
Stéphane Borel's avatar
Stéphane Borel committed
876
    }
877 878

    if( p_ifo->vmg.manager_inf.i_vts_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
879
    {
880 881
        free( p_ifo->vmg.vts_inf.p_vts_attr );
        free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte );
Stéphane Borel's avatar
Stéphane Borel committed
882
    }
883 884 885

    /* free parental information structures */
    if( p_ifo->vmg.manager_inf.i_parental_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
886
    {
887 888 889 890 891 892 893 894 895 896
        for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ )
        {
            for( j = 0 ; j < 8 ; j++ )
            {
                free( p_ifo->vmg.parental_inf.p_parental_mask[i].ppi_mask[j] );
            }
        }

        free( p_ifo->vmg.parental_inf.p_parental_mask );
        free( p_ifo->vmg.parental_inf.p_parental_desc );
Stéphane Borel's avatar
Stéphane Borel committed
897
    }
898 899

    if( p_ifo->vmg.manager_inf.i_title_unit_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
900
    {
901
        FreeTitleUnit( &p_ifo->vmg.title_unit );
Stéphane Borel's avatar
Stéphane Borel committed
902
    }
903 904

    if( p_ifo->vmg.manager_inf.i_title_inf_start_sector )
Stéphane Borel's avatar
Stéphane Borel committed
905
    {
906
        free( p_ifo->vmg.title_inf.p_attr );
Stéphane Borel's avatar
Stéphane Borel committed
907 908
    }

909 910 911 912 913 914
    FreeTitle( &p_ifo->vmg.title );

    free( p_ifo );

    return;
}
Stéphane Borel's avatar
Stéphane Borel committed
915
/*
916
 * Function common to Video Manager and Video Title set Processing
Stéphane Borel's avatar
Stéphane Borel committed
917 918 919
 */

/*****************************************************************************
920 921 922 923 924
 * ReadTitle : Fills the title structure.
 *****************************************************************************
 * Titles are logical stream units that correspond to a whole inside the dvd.
 * Several title can point to the same part of the physical DVD, and give
 * map to different anglesfor instance.
Stéphane Borel's avatar
Stéphane Borel committed
925
 *****************************************************************************/
926
static int ReadTitle( ifo_t * p_ifo, title_t * p_title, off_t i_pos )
Stéphane Borel's avatar
Stéphane Borel committed
927
{
928 929 930 931 932 933
    u8          pi_buffer[DVD_LB_SIZE];
    u8 *        p_current;
    off_t       i_start;
    int         i;

    p_current = FillBuffer( p_ifo, pi_buffer, i_pos );
Stéphane Borel's avatar
Stéphane Borel committed
934

935
    i_start = p_ifo->i_pos;
Stéphane Borel's avatar
Stéphane Borel committed
936

937
//fprintf( stderr, "PGC @ %lld\n",p_ifo->i_pos  );
938

939 940 941
    DumpBits( p_ifo, pi_buffer, &p_current, 2);
    p_title->i_chapter_nb = ReadByte( p_ifo, pi_buffer, &p_current );
    p_title->i_cell_nb = ReadByte( p_ifo, pi_buffer, &p_current );
942
//fprintf( stderr, "title: Prg: %d Cell: %d\n",p_title->i_chapter_nb,p_title->i_cell_nb  );
943 944
    p_title->i_play_time = ReadDouble( p_ifo, pi_buffer, &p_current );
    p_title->i_prohibited_user_op = ReadDouble( p_ifo, pi_buffer, &p_current );