📄 ifo.c
字号:
/***************************************************************************** * ifo.c: Functions for ifo parsing ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN * $Id: ifo.c,v 1.6 2003/10/25 00:49:13 sam Exp $ * * Authors: St閜hane Borel <stef@via.ecp.fr> * German Tischler <tanis@gaspode.franken.de> * * based on: * - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at> * - IFO structure documentation by Thomas Mirlacher, Bj鰎n Englund, * H錵an Hjort * * 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 *****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <vlc/vlc.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <string.h>#include <fcntl.h>#ifdef GOD_DAMN_DMCA# include "dvdcss.h"#else# include <dvdcss/dvdcss.h>#endif#include "dvd.h"#include "ifo.h"#include "udf.h"/***************************************************************************** * Local prototypes *****************************************************************************/void CommandRead ( command_desc_t );static int ReadTitle ( ifo_t * , title_t *, int, int );static int FreeTitle ( title_t * );static int ReadUnitInf ( ifo_t * , unit_inf_t *, int, int );static int FreeUnitInf ( unit_inf_t * );static int ReadTitleUnit ( ifo_t * , title_unit_t *, int );static int FreeTitleUnit ( title_unit_t * );static int ReadVobuMap ( ifo_t * , vobu_map_t *, int );static int FreeVobuMap ( vobu_map_t * );static int ReadCellInf ( ifo_t * , cell_inf_t *, int );static int FreeCellInf ( cell_inf_t * );static int FreeTitleSet ( vts_t * );static uint8_t* FillBuffer ( ifo_t *, uint8_t *, int );static uint8_t ReadByte ( ifo_t *, uint8_t *, uint8_t ** );static void ReadBytes ( ifo_t *, uint8_t *, uint8_t **, uint8_t *, int );static void DumpBytes ( ifo_t *, uint8_t *, uint8_t **, int );static uint16_t ReadWord ( ifo_t *, uint8_t *, uint8_t ** );static uint32_t ReadDouble ( ifo_t *, uint8_t *, uint8_t ** );static uint64_t ReadQuad ( ifo_t *, uint8_t *, uint8_t ** );/* * IFO Management. *//***************************************************************************** * IfoCreate : Creates an ifo structure and prepares for parsing directly * on DVD device *****************************************************************************/int IfoCreate( thread_dvd_data_t * p_dvd ){ p_dvd->p_ifo = malloc( sizeof(ifo_t) ); if( p_dvd->p_ifo == NULL ) { return -1; } /* memset to 0 to avoid crashing on deallocation later */ memset( p_dvd->p_ifo, 0, sizeof(ifo_t) ); /* if we are here the dvd device has already been opened */ p_dvd->p_ifo->dvdhandle = p_dvd->dvdhandle; return 0;}/***************************************************************************** * IfoInit : Reads information from the management table. *****************************************************************************/int IfoInit( ifo_t * p_ifo ){ uint8_t p_buf[DVD_LB_SIZE]; uint8_t * p_tmp; uint64_t i_temp; int i, j, k; int i_start; /* find the start sector of video information on the dvd */ p_ifo->i_start = DVDUDFFindFile( p_ifo->dvdhandle, "/VIDEO_TS/VIDEO_TS.IFO" ); if( !p_ifo->i_start ) return -1; p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start ); /*i_start = p_ifo->i_pos; */ /* * read the video manager information table */#define MGINF p_ifo->vmg.manager_inf /*fprintf( stderr, "VMGI\n" ); */ ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.psz_id, 12 ); MGINF.psz_id[12] = '\0'; MGINF.i_vmg_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 12 ); MGINF.i_vmg_inf_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 1 ); MGINF.i_spec_ver = ReadByte( p_ifo, p_buf, &p_tmp ); MGINF.i_cat = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_volume_nb = ReadWord( p_ifo, p_buf, &p_tmp ); MGINF.i_volume = ReadWord( p_ifo, p_buf, &p_tmp ); MGINF.i_disc_side = ReadByte( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 19 ); MGINF.i_title_set_nb = ReadWord( p_ifo, p_buf, &p_tmp ); ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.ps_provider_id, 32 ); MGINF.i_pos_code = ReadQuad( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 24 ); MGINF.i_vmg_inf_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_first_play_title_start_byte = ReadDouble( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 56 ); MGINF.i_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_title_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_title_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_parental_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_vts_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_text_data_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); MGINF.i_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 32 ); DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); DumpBytes( p_ifo, p_buf, &p_tmp, 1 ); MGINF.i_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "vmgi audio nb : %d\n", MGINF.i_audio_nb ); */ for( i = 0 ; i < 8 ; i++ ) { i_temp = ReadQuad( p_ifo, p_buf, &p_tmp ); } DumpBytes( p_ifo, p_buf, &p_tmp, 17 ); MGINF.i_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "vmgi subpic nb : %d\n", MGINF.i_spu_nb ); */ for( i = 0 ; i < MGINF.i_spu_nb ; i++ ) { ReadBytes( p_ifo, p_buf, &p_tmp, (uint8_t*)(&i_temp), 6 ); /* FIXME : take care of endianness */ } /* * read first play title. */ /*fprintf(stderr,"readtitle %i\n", MGINF.i_first_play_title_start_byte & 0x7ff ); */ if( ReadTitle( p_ifo, &p_ifo->vmg.title, p_ifo->i_start + OFF2LB( MGINF.i_first_play_title_start_byte ), MGINF.i_first_play_title_start_byte & 0x7ff ) < 0 ) { return -1; } /* * fills the title information structure. */#define TITINF p_ifo->vmg.title_inf if( MGINF.i_title_inf_start_sector ) { p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start + MGINF.i_title_inf_start_sector ); /*fprintf( stderr, "title inf %d\n", p_ifo->i_pos ); */ TITINF.i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "title_inf: TTU nb %d\n", TITINF.i_title_nb ); */ DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); TITINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp ); /* parsing of title attributes */ TITINF.p_attr = malloc( TITINF.i_title_nb *sizeof(title_attr_t) ); if( TITINF.p_attr == NULL ) { return -1; } for( i = 0 ; i < TITINF.i_title_nb ; i++ ) { TITINF.p_attr[i].i_play_type = ReadByte( p_ifo, p_buf, &p_tmp ); TITINF.p_attr[i].i_angle_nb = ReadByte( p_ifo, p_buf, &p_tmp ); TITINF.p_attr[i].i_chapter_nb = ReadWord( p_ifo, p_buf, &p_tmp ); TITINF.p_attr[i].i_parental_id = ReadWord( p_ifo, p_buf, &p_tmp ); TITINF.p_attr[i].i_title_set_num = ReadByte( p_ifo, p_buf, &p_tmp ); TITINF.p_attr[i].i_title_num = ReadByte( p_ifo, p_buf, &p_tmp ); TITINF.p_attr[i].i_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "title_inf: %d %d %d\n", TITINF.p_attr[i].i_chapter_nb, TITINF.p_attr[i].i_title_set_num, TITINF.p_attr[i].i_title_num ); */ } } else { TITINF.p_attr = NULL; }#undef TITINF /* * fills the title unit structure. */ if( MGINF.i_title_unit_start_sector ) { if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit, p_ifo->i_start + MGINF.i_title_unit_start_sector ) < 0 ) { return -1; } } /* * fills the structure about parental information. */#define PARINF p_ifo->vmg.parental_inf if( MGINF.i_parental_inf_start_sector ) { p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start + MGINF.i_parental_inf_start_sector ); i_start = p_ifo->i_pos; /*fprintf( stderr, "PTL\n" ); */ PARINF.i_country_nb = ReadWord( p_ifo, p_buf, &p_tmp ); PARINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp ); PARINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp ); PARINF.p_parental_desc = malloc( PARINF.i_country_nb * sizeof(parental_desc_t) ); if( PARINF.p_parental_desc == NULL ) { return -1; } for( i = 0 ; i < PARINF.i_country_nb ; i++ ) { ReadBytes( p_ifo, p_buf, &p_tmp, PARINF.p_parental_desc[i].ps_country_code, 2 ); DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); PARINF.p_parental_desc[i].i_parental_mask_start_byte = ReadWord( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); } PARINF.p_parental_mask = malloc( PARINF.i_country_nb * sizeof(parental_mask_t) ); if( PARINF.p_parental_mask == NULL ) { return -1; } for( i = 0 ; i < PARINF.i_country_nb ; i++ ) { p_tmp = FillBuffer( p_ifo, p_buf, i_start + OFF2LB( PARINF.p_parental_desc[i].i_parental_mask_start_byte ) ) + (PARINF.p_parental_desc[i].i_parental_mask_start_byte & 0x7ff); for( j = 0 ; j < 8 ; j++ ) { PARINF.p_parental_mask[i].ppi_mask[j] = malloc( ( PARINF.i_vts_nb + 1 ) * sizeof(uint16_t) ); if( PARINF.p_parental_mask[i].ppi_mask[j] == NULL ) { return -1; } for( k = 0 ; k < PARINF.i_vts_nb + 1 ; k++ ) { PARINF.p_parental_mask[i].ppi_mask[j][k] = ReadWord( p_ifo, p_buf, &p_tmp ); } } } }#undef PARINF /* * information and attributes about for each vts. */#define VTSINF p_ifo->vmg.vts_inf if( MGINF.i_vts_inf_start_sector ) { uint64_t i_temp; p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start + MGINF.i_vts_inf_start_sector ); i_start = p_ifo->i_pos; /*fprintf( stderr, "VTS ATTR\n" ); */ VTSINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp );; /*fprintf( stderr, "VTS ATTR Nb: %d\n", VTSINF.i_vts_nb ); */ DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); VTSINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp ); VTSINF.pi_vts_attr_start_byte = malloc( VTSINF.i_vts_nb * sizeof(uint32_t) ); if( VTSINF.pi_vts_attr_start_byte == NULL ) { return -1; } for( i = 0 ; i < VTSINF.i_vts_nb ; i++ ) { VTSINF.pi_vts_attr_start_byte[i] = ReadDouble( p_ifo, p_buf, &p_tmp ); } VTSINF.p_vts_attr = malloc( VTSINF.i_vts_nb * sizeof(vts_attr_t) ); if( VTSINF.p_vts_attr == NULL ) { return -1; } for( i = 0 ; i < VTSINF.i_vts_nb ; i++ ) { p_tmp = FillBuffer( p_ifo, p_buf, i_start + OFF2LB( VTSINF.pi_vts_attr_start_byte[i] ) ) + ( VTSINF.pi_vts_attr_start_byte[i] & 0x7ff ); VTSINF.p_vts_attr[i].i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp ); VTSINF.p_vts_attr[i].i_cat_app_type = ReadDouble( p_ifo, p_buf, &p_tmp ); DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); DumpBytes( p_ifo, p_buf, &p_tmp, 1 ); VTSINF.p_vts_attr[i].i_vts_menu_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "m audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_audio_nb ); */ for( j = 0 ; j < 8 ; j++ ) { i_temp = ReadQuad( p_ifo, p_buf, &p_tmp ); } DumpBytes( p_ifo, p_buf, &p_tmp, 17 ); VTSINF.p_vts_attr[i].i_vts_menu_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "m subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_spu_nb ); */ for( j = 0 ; j < 28 ; j++ ) { /* FIXME : Fix endianness issue here */ ReadBytes( p_ifo, p_buf, &p_tmp, (uint8_t*)(&i_temp), 6 ); } DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); DumpBytes( p_ifo, p_buf, &p_tmp, 2 ); DumpBytes( p_ifo, p_buf, &p_tmp, 1 ); VTSINF.p_vts_attr[i].i_vts_title_audio_nb = ReadDouble( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "tt audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_audio_nb ); */ for( j = 0 ; j < 8 ; j++ ) { i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );; } DumpBytes( p_ifo, p_buf, &p_tmp, 17 ); VTSINF.p_vts_attr[i].i_vts_title_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp ); /*fprintf( stderr, "tt subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_spu_nb ); */ for( j = 0 ; j < 28 /*VTSINF.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ ) { /* FIXME : Fix endianness issue here */ ReadBytes( p_ifo, p_buf, &p_tmp, (uint8_t*)(&i_temp), 6 ); } } }#undef VTSINF /* * global cell map. */ if( MGINF.i_cell_inf_start_sector ) { if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf, p_ifo->i_start + MGINF.i_cell_inf_start_sector ) < 0 ) { return -1; } } /* * global vob unit map. */ if( MGINF.i_vobu_map_start_sector ) { if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map, p_ifo->i_start + MGINF.i_vobu_map_start_sector ) < 0 ) { return -1; } }#undef MGINF p_ifo->vts.b_initialized = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -