]> git.sesse.net Git - vlc/commitdiff
-UDF filesystem support so that we know the location of the first video
authorStéphane Borel <stef@videolan.org>
Sun, 18 Feb 2001 01:42:05 +0000 (01:42 +0000)
committerStéphane Borel <stef@videolan.org>
Sun, 18 Feb 2001 01:42:05 +0000 (01:42 +0000)
related file with 100% reliability (great change that should make DVDs
with binaries and extra stuff work with vlc).

-Correction of a bug in ifo reading that falsified the adress of
video titles.

-Changed the method for selecting title at start. It is _not_ reliable
though, but it is better than the preceding one.

Makefile.in
plugins/dvd/dvd_css.c
plugins/dvd/dvd_ifo.c
plugins/dvd/dvd_udf.c
plugins/dvd/dvd_udf.h
plugins/dvd/input_dvd.c
plugins/dvd/input_dvd.h

index 3f0ce12ea8ab1993e86a6ec64ed227b6ae7e9685..f37f6305c53e1109499ceed7a849ce389de10e1d 100644 (file)
@@ -294,6 +294,7 @@ PLUGIN_DUMMY =      plugins/dummy/dummy.o \
 PLUGIN_DVD =   plugins/dvd/dvd.o \
                plugins/dvd/input_dvd.o \
                plugins/dvd/dvd_ifo.o \
+               plugins/dvd/dvd_udf.o \
                plugins/dvd/dvd_css.o
 
 PLUGIN_ESD =   plugins/esd/esd.o \
index 683844645d63257179db8af6062c37cc46d2e9ba..70e5f36247728a0a206a5c0ee7da1adcfbb7ec74 100644 (file)
@@ -2,7 +2,7 @@
  * dvd_css.c: Functions for DVD authentification and unscrambling
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: dvd_css.c,v 1.9 2001/02/15 21:03:27 stef Exp $
+ * $Id: dvd_css.c,v 1.10 2001/02/18 01:42:04 stef Exp $
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
@@ -1052,7 +1052,7 @@ int CSSGetKeys( css_t * p_css )
     int         i_highest;
     int         i,j,k;
 
-    for( i_title = 0 ; i_title < 1/*p_css->i_title_nb*/ ; i_title++ )
+    for( i_title = 0 ; i_title < p_css->i_title_nb ; i_title++ )
     {
         /* Initialization for each title */
         memset( p_title_key, 0, 10 );
index a19970bb2c5b91cabca379dc923d4bfcd0452198..24f8ffaf7c190a4dfab5b6de0fbc97a32b9d9f61 100644 (file)
@@ -2,7 +2,7 @@
  * dvd_ifo.c: Functions for ifo parsing
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: dvd_ifo.c,v 1.8 2001/02/15 21:03:27 stef Exp $
+ * $Id: dvd_ifo.c,v 1.9 2001/02/18 01:42:05 stef Exp $
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
@@ -38,6 +38,7 @@
 
 #include "intf_msg.h"
 #include "dvd_ifo.h"
+#include "dvd_udf.h"
 #include "input_dvd.h"
 
 void CommandRead( ifo_command_t );
@@ -46,57 +47,6 @@ void CommandRead( ifo_command_t );
  * IFO Management.
  */
 
-/*****************************************************************************
- * IfoFindVMG : When reading directly on a device, finds the offset to the
- * beginning of video_ts.ifo.
- *****************************************************************************/
-static int IfoFindVMG( ifo_t* p_ifo )
-{
-    char    psz_ifo_start[12] = "DVDVIDEO-VMG";
-    char    psz_test[12];
-
-    read( p_ifo->i_fd, psz_test, 12 );
-
-    while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
-    {
-        /* The start of ifo file is on a sector boundary */
-        p_ifo->i_pos = lseek( p_ifo->i_fd,
-                              p_ifo->i_pos + DVD_LB_SIZE,
-                              SEEK_SET );
-        read( p_ifo->i_fd, psz_test, 12 );
-    }
-    p_ifo->i_off = p_ifo->i_pos;
-
-fprintf( stderr, "VMG Off : %lld\n", (long long)(p_ifo->i_off) );
-
-    return 0;
-}
-
-/*****************************************************************************
- * IfoFindVTS : beginning of vts_*.ifo.
- *****************************************************************************/
-static int IfoFindVTS( ifo_t* p_ifo )
-{
-    char    psz_ifo_start[12] = "DVDVIDEO-VTS";
-    char    psz_test[12];
-
-    read( p_ifo->i_fd, psz_test, 12 );
-
-    while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
-    {
-        /* The start of ifo file is on a sector boundary */
-        p_ifo->i_pos = lseek( p_ifo->i_fd,
-                              p_ifo->i_pos + DVD_LB_SIZE,
-                              SEEK_SET );
-        read( p_ifo->i_fd, psz_test, 12 );
-    }
-    p_ifo->i_off = p_ifo->i_pos;
-
-fprintf( stderr, "VTS Off : %lld\n", (long long)(p_ifo->i_off) );
-
-    return 0;
-}
-
 /*****************************************************************************
  * IfoInit : Creates an ifo structure and prepares for parsing directly
  * on DVD device.
@@ -104,15 +54,16 @@ fprintf( stderr, "VTS Off : %lld\n", (long long)(p_ifo->i_off) );
 ifo_t IfoInit( int i_fd )
 {
     ifo_t       ifo;
+    u32         i_lba;
     
     /* If we are here the dvd device has already been opened */
     ifo.i_fd = i_fd;
-    /* No data at the beginning of the disk
-     * 512000 bytes is just another value :) */
-    ifo.i_pos = lseek( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET );
-    /* FIXME : use udf filesystem to find the beginning of the file */
-    IfoFindVMG( &ifo );
-    
+
+    i_lba = UDFFindFile( i_fd, "/VIDEO_TS/VIDEO_TS.IFO");
+
+    ifo.i_off = (off_t)(i_lba) * DVD_LB_SIZE;
+    ifo.i_pos = lseek( ifo.i_fd, ifo.i_off, SEEK_SET );
+
     return ifo;
 }
 
@@ -648,6 +599,7 @@ static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
         GETC( &ptr.p_tts[i].i_tts_nb );
         GETC( &ptr.p_tts[i].i_vts_ttn );
         GETL( &ptr.p_tts[i].i_ssector );
+//fprintf( stderr, "PTR: %d %d %d\n",ptr.p_tts[i].i_tts_nb,ptr.p_tts[i].i_vts_ttn, ptr.p_tts[i].i_ssector );
     }
 
     return ptr;
@@ -1030,56 +982,56 @@ static vts_t ReadVTS( ifo_t* p_ifo )
     vts.mat = ReadVTSInfMat( p_ifo );
     if( vts.mat.i_ptt_srpt_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
     }
     if( vts.mat.i_m_pgci_ut_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.pgci_ut = ReadUnitTable( p_ifo );
     }
     if( vts.mat.i_pgcit_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.pgci_ti = ReadUnit( p_ifo );
     }
     if( vts.mat.i_tmap_ti_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.tmap_ti = ReadVTSTimeMap( p_ifo );
     }
     if( vts.mat.i_m_c_adt_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.m_c_adt = ReadCellInf( p_ifo );
     }
     if( vts.mat.i_m_vobu_admap_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.m_vobu_admap = ReadMap( p_ifo );
     }
     if( vts.mat.i_c_adt_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.c_adt = ReadCellInf( p_ifo );
     }
     if( vts.mat.i_vobu_admap_ssector )
     {
-        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+        p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
                         vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
                         SEEK_SET );
         vts.vobu_admap = ReadMap( p_ifo );
@@ -1113,19 +1065,24 @@ void IfoRead( ifo_t* p_ifo )
         p_ifo->b_error = 1;
         return;
     }
+
     for( i=0 ; i<p_ifo->vmg.mat.i_tts_nb ; i++ )
     {
 
         intf_WarnMsg( 2, "ifo: initializing VTS %d", i+1 );
 
-        i_off = (off_t)(p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector) *DVD_LB_SIZE;
+        i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector ) *DVD_LB_SIZE
+                       + p_ifo->i_off;
+
         p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
-fprintf( stderr, "%lld\n" , p_ifo->i_pos );
 
-        /* FIXME : use udf filesystem to avoid this */
-        IfoFindVTS( p_ifo );
+        /* FIXME : I really don't know why udf find file
+         * does not give the exact beginning of file */
+
         p_ifo->p_vts[i] = ReadVTS( p_ifo );
+
     }
+
     return; 
 }
 
index 136ff6367749144ecf86ab2733c45258c187c978..1434db25fd1bef7ca7ae5a681c656c65906488d9 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * dvd_udf.c: udf filesystem tools.
  * ---
- * Mainly used to find asolute logical block adress of *.ifo files
+ * Mainly used to find asolute logical block adress of *.ifo files. It only
+ * contains the basic udf handling functions
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: dvd_udf.c,v 1.1 2001/02/15 21:03:27 stef Exp $
+ * $Id: dvd_udf.c,v 1.2 2001/02/18 01:42:05 stef Exp $
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
-#include <netinet/in.h>
 
 #include "common.h"
 #include "intf_msg.h"
+#include "dvd_css.h"
+#include "dvd_ifo.h"
 #include "input_dvd.h"
 
-/*
- * Local structures
- */
+#define UDFADshort      1
+#define UDFADlong       2
+#define UDFADext        4
+
 typedef struct partition_s
 {
-       int     i_valid;
-       u8      pi_volume_desc[128];
-       u16     i_flags;
-       u16     i_number;
-       u8      pi_contents[32];
-       u32     i_accessType;
-       u32     i_start;
-       u32     i_length;
+    boolean_t   b_valid;
+    u8          pi_volume_desc[128];
+    u16         i_flags;
+    u16         i_number;
+    u8          pi_contents[32];
+    u32         i_access_type;
+    u32         i_start;
+    u32         i_length;
+    int         i_fd;
 } partition_t;
 
 typedef struct ad_s
 {
-       u32     i_location;
-       u32     i_length;
-       u8      i_flags;
-       u16     i_partition;
+    u32         i_location;
+    u32         i_length;
+    u8          i_flags;
+    u16         i_partition;
 } ad_t;
 
-/*
- * Local functions
- */
+/* for direct data access, LSB first */
+#define GETN1(p) ((u8)pi_data[p])
+#define GETN2(p) ((u16)pi_data[p]|((u16)pi_data[(p)+1]<<8))
+#define GETN4(p) ((u32)pi_data[p]|((u32)pi_data[(p)+1]<<8)|((u32)pi_data[(p)+2]<<16)|((u32)pi_data[(p)+3]<<24))
+#define GETN(p,n,target) memcpy(target,&pi_data[p],n)
+
+
+/*****************************************************************************
+ * UDFReadLB: reads absolute Logical Block of the disc
+ * ---
+ * returns number of read bytes on success, 0 on error
+ *****************************************************************************/
+static int UDFReadLB( int i_fd, off_t i_lba, size_t i_block_count, u8 *pi_data )
+{
+    if( i_fd < 0 )
+    {
+        return 0;
+    }
+
+    if( lseek( i_fd, i_lba * (off_t) DVD_LB_SIZE, SEEK_SET ) < 0 )
+    {
+        intf_ErrMsg( "UDF: Postion not found" );
+        return 0;
+    }
+
+    return read( i_fd, pi_data, i_block_count *DVD_LB_SIZE);
+}
+
 
 /*****************************************************************************
- * UDFDecode: decode udf data that is unicode encoded
+ * UDFDecode: decode unicode encoded udf data
  *****************************************************************************/
 static int UDFDecode( u8 * pi_data, int i_len, char * psz_target )
 {
-       int p = 1;
-    int i = 0;
+    int     p = 1;
+    int     i = 0;
 
-       if( !( pi_data[0] & 0x18 ) )
+    if( !( pi_data[0] & 0x18 ) )
     {
-               psz_target[0] ='\0';
-               return 0;
-       }
+        psz_target[0] = '\0';
+        return 0;
+    }
 
-       if( data[0] & 0x10 )
-    {          
+    if( pi_data[0] & 0x10 )
+    {
         /* ignore MSB of unicode16 */
-               p++;
+        p++;
 
-               while( p < i_len )
+        while( p < i_len )
         {
-                       psz_target[i++] = pi_data[p+=2];
+            psz_target[i++] = pi_data[p+=2];
         }
-       }
+    }
     else
     {
-               while( p < i_len )
+        while( p < i_len )
         {
-                       psz_target[i++] = pi_data[p++];
+            psz_target[i++] = pi_data[p++];
         }
-       }
-       
-       psz_target[i]='\0';
+    }
+    
+    psz_target[i]='\0';
 
-       return 0;
+    return 0;
 }
 
+#if 0
+/**
+ *
+ **/
+
+int UDFEntity (u8 *data, u8 *Flags, char *Identifier)
+{
+    Flags[0] = data[0];
+    strncpy (Identifier, &data[1], 5);
+
+    return 0;
+}
+#endif
+
+
 /*****************************************************************************
- * UDFInit: some check and initialization in udf filesystem
+ * UDFDescriptor: gives a tag ID from your data to find out what it refers to
  *****************************************************************************/
-int UDFInit( u8 * pi_data, udf_t * p_udf )
+static int UDFDescriptor( u8 * pi_data, u16 * pi_tag_id )
 {
-       u32i    lbsize,MT_L,N_PM;
+    pi_tag_id[0] = GETN2( 0 );
+    /* TODO: check CRC 'n stuff */
 
-       UDFDecode( &pi_data[84], 128, p_udf->psz_volume_desc );
-       lbsize  = GETN4(212);           // should be 2048
-       MT_L    = GETN4(264);           // should be 6
-       N_PM    = GETN4(268);           // should be 1
+    return 0;
+}
+
+
+/*****************************************************************************
+ * UDFExtendAD: main volume information
+ *****************************************************************************/
+static int UDFExtentAD (u8 * pi_data, u32 * pi_length, u32 * pi_location)
+{
+    pi_length[0] = GETN4( 0 );
+    pi_location[0] = GETN4( 4 );
 
-       if( lbsize != DVD_LB_SIZE )
+    return 0;
+}
+
+
+/*****************************************************************************
+ * UDFAD: file set information
+ *****************************************************************************/
+static int UDFAD( u8 * pi_data, struct ad_s * p_ad, u8 i_type,
+                  struct partition_s partition )
+{
+    p_ad->i_length = GETN4( 0 );
+    p_ad->i_flags = p_ad->i_length >> 30;
+    p_ad->i_length &= 0x3FFFFFFF;
+
+    switch( i_type )
     {
-               return 1;
+        case UDFADshort:
+            p_ad->i_location = GETN4( 4 );
+            /* use number of current partition */
+            p_ad->i_partition = partition.i_number;
+             break;
+
+        case UDFADlong:
+            p_ad->i_location = GETN4( 4 );
+            p_ad->i_partition = GETN2( 8 );
+            break;
+
+        case UDFADext:
+            p_ad->i_location = GETN4( 12 );
+            p_ad->i_partition = GETN2( 16 );
+            break;
     }
 
     return 0;
 }
 
+
 /*****************************************************************************
- * UDFFileEntry:
+ * UDFICB: takes Information Control Block from pi_data
  *****************************************************************************/
-int UDFFileEntry (uint8_t *data, uint8_t *FileType, struct AD *ad)
-{
-       uint8_t filetype;
-       uint16_t flags;
-       uint32_t L_EA,L_AD;
-       int p;
-
-       UDFICB(&data[16],&filetype,&flags);
-       FileType[0]=filetype;
-       L_EA=GETN4(168);
-       L_AD=GETN4(172);
-       p=176+L_EA;
-
-       while (p<176+L_EA+L_AD) {
-               switch (flags&0x07) {
-               case 0:
-                       UDFAD (&data[p], ad, UDFADshort);
-                       p += 0x08;
-                       break;
-               case 1:
-                       UDFAD (&data[p], ad, UDFADlong);
-                       p += 0x10;
-                       break;
-               case 2: UDFAD (&data[p], ad, UDFADext);
-                       p += 0x14;
-                       break;
-               case 3:
-                       switch (L_AD) {
-                       case 0x08:
-                               UDFAD (&data[p], ad, UDFADshort);
-                               break;
-                       case 0x10:
-                               UDFAD (&data[p], ad, UDFADlong);
-                               break;
-                       case 0x14:
-                               UDFAD (&data[p], ad, UDFADext);
-                               break;
-                       }
-               default:
-                       p += L_AD;
-                       break;
-               }
-       }
-
-       return 0;
+static int UDFICB( u8 * pi_data, u8 * pi_file_type, u16 * pi_flags)
+{
+    pi_file_type[0] = GETN1( 11 );
+    pi_flags[0] = GETN2( 18 );
+
+    return 0;
+}
+
+
+/*****************************************************************************
+ * UDFPartition: gets partition descriptor
+ *****************************************************************************/
+static int UDFPartition( u8 * pi_data, u16 * pi_flags, u16 * pi_nb,
+                         char * ps_contents, u32 * pi_start, u32 * pi_length )
+{
+    pi_flags[0] = GETN2( 20 );
+    pi_nb[0] = GETN2( 22 );
+    GETN( 24, 32, ps_contents );
+    pi_start[0] = GETN4( 188 );
+    pi_length[0] = GETN4( 192 );
+
+    return 0;
+}
+
+
+/*****************************************************************************
+ * UDFLogVolume: reads the volume descriptor and checks the parameters
+ * ---
+ * returns 0 on OK, 1 on error
+ *****************************************************************************/
+static int UDFLogVolume(u8 * pi_data, char * p_volume_descriptor )
+{
+    u32 i_lb_size;
+    u32 i_MT_L;
+    u32 i_N_PM;
+
+    UDFDecode( &pi_data[84], 128, p_volume_descriptor );
+
+    i_lb_size = GETN4( 212 );        // should be 2048
+    i_MT_L = GETN4( 264 );        // should be 6
+    i_N_PM = GETN4( 268 );        // should be 1
+
+    if( i_lb_size != DVD_LB_SIZE )
+    {
+        intf_ErrMsg( "UDF: Non valid sector size (%d)", i_lb_size );
+        return 1;
+    }
+
+    return 0;
+}
+
+
+/*****************************************************************************
+ * UDFFileEntry: fills a ad_t struct with information at pi_data
+ *****************************************************************************/
+static int UDFFileEntry( u8 * pi_data, u8 * pi_file_type, struct ad_s * p_ad,
+                         struct partition_s partition )
+{
+    u8      i_file_type;
+    u16     i_flags;
+    u32     i_L_EA;
+    u32     i_L_AD;
+    int     p;
+
+    UDFICB( &pi_data[16], &i_file_type, &i_flags );
+
+    pi_file_type[0] = i_file_type;
+    i_L_EA = GETN4( 168 );
+    i_L_AD = GETN4( 172 );
+    p = 176 + i_L_EA;
+
+    while( p < 176 + i_L_EA + i_L_AD )
+    {
+        switch( i_flags & 0x07 )
+        {
+        case 0:
+            UDFAD( &pi_data[p], p_ad, UDFADshort, partition );
+            p += 0x08;
+            break;
+        case 1:
+            UDFAD( &pi_data[p], p_ad, UDFADlong, partition );
+            p += 0x10;
+            break;
+        case 2:
+            UDFAD( &pi_data[p], p_ad, UDFADext, partition );
+            p += 0x14;
+            break;
+        case 3:
+            switch( i_L_AD )
+            {
+            case 0x08:
+                UDFAD( &pi_data[p], p_ad, UDFADshort, partition );
+                break;
+            case 0x10:
+                UDFAD( &pi_data[p], p_ad, UDFADlong, partition );
+                break;
+            case 0x14:
+                UDFAD( &pi_data[p], p_ad, UDFADext, partition );
+                break;
+            }
+        default:
+            p += i_L_AD;
+            break;
+        }
+    }
+
+    return 0;
 }
 
+
 /*****************************************************************************
- * UDFFileIdentifier:
+ * UDFFileIdentifier: gives filename and characteristics of pi_data
  *****************************************************************************/
-int UDFFileIdentifier (uint8_t *data, uint8_t *FileCharacteristics, char *FileName, struct AD *FileICB)
+static int UDFFileIdentifier( u8 * pi_data, u8 * pi_file_characteristics,
+                              char * psz_filename, struct ad_s * p_file_icb,
+                              struct partition_s partition )
 {
-       uint8_t L_FI;
-       uint16_t L_IU;
+    u8      i_L_FI;
+    u16     i_L_IU;
   
-       FileCharacteristics[0]=GETN1(18);
-       L_FI=GETN1(19);
-       UDFAD(&data[20],FileICB,UDFADlong);
-       L_IU=GETN2(36);
+    pi_file_characteristics[0] = GETN1( 18 );
+    i_L_FI = GETN1( 19 );
+    UDFAD( &pi_data[20], p_file_icb, UDFADlong, partition );
+    i_L_IU = GETN2( 36 );
 
-       if (L_FI)
-               _Unicodedecode (&data[38+L_IU],L_FI,FileName);
-       else
-               FileName[0]='\0';
+    if( i_L_FI )
+    {
+        UDFDecode( &pi_data[38+i_L_IU], i_L_FI, psz_filename );
+    }
+    else
+    {
+        psz_filename[0]='\0';
+    }
 
-       return 4*((38+L_FI+L_IU+3)/4);
+    return  4 * ( ( 38 + i_L_FI + i_L_IU + 3 ) / 4 );
 }
 
 
+/*****************************************************************************
+ * UDFMapICB: Maps ICB to FileAD
+ * ---
+ * ICB: Location of ICB of directory to scan
+ * FileType: Type of the file
+ * File: Location of file the ICB is pointing to
+ * return 1 on success, 0 on error;
+ *****************************************************************************/
+static int UDFMapICB( struct ad_s icb, u8 * pi_file_type, struct ad_s * p_file,
+                      struct partition_s partition )
+{
+    u8      pi_lb[DVD_LB_SIZE];
+    u32     i_lba;
+    u16     i_tag_id;
+
+    i_lba = partition.i_start + icb.i_location;
+
+    do
+    {
+        if( !UDFReadLB( partition.i_fd, i_lba++, 1, pi_lb ) )
+        {
+            i_tag_id = 0;
+        }
+        else
+        {
+            UDFDescriptor( pi_lb , &i_tag_id );
+        }
+
+        if( i_tag_id == 261 )
+        {
+            UDFFileEntry( pi_lb, pi_file_type, p_file, partition );
+            return 1;
+        }
+
+    } while( ( i_lba <= partition.i_start + icb.i_location +
+               ( icb.i_length - 1 ) / DVD_LB_SIZE ) && ( i_tag_id != 261 ) );
+
+    return 0;
+}
+
+/*****************************************************************************
+ * UDFScanDir: serach filename in dir
+ * ---
+ * Dir: Location of directory to scan
+ * FileName: Name of file to look for
+ * FileICB: Location of ICB of the found file
+ * return 1 on success, 0 on error;
+ *****************************************************************************/
+static int UDFScanDir( struct ad_s dir, char * psz_filename,
+                       struct ad_s * p_file_icb, struct partition_s partition )
+{
+    u8      pi_lb[DVD_LB_SIZE];
+    u32     i_lba;
+    u16     i_tag_id;
+    u8      i_file_char;
+    char    psz_temp[DVD_LB_SIZE];
+    int     p;
+  
+    /* Scan dir for ICB of file */
+    i_lba = partition.i_start + dir.i_location;
+
+    do
+    {
+        if( !UDFReadLB( partition.i_fd, i_lba++, 1, pi_lb ) )
+        {
+            i_tag_id = 0;
+        }
+        else
+        {
+            p=0;
+            while( p < DVD_LB_SIZE )
+            {
+                UDFDescriptor( &pi_lb[p], &i_tag_id );
+
+                if( i_tag_id == 257 )
+                {
+                    p += UDFFileIdentifier( &pi_lb[p], &i_file_char,
+                                            psz_temp, p_file_icb, partition );
+                    if( !strcasecmp( psz_filename, psz_temp ) )
+                    {
+                        return 1;
+                    }
+                }
+                else
+                {
+                    p = DVD_LB_SIZE;
+                }
+            }
+        }
+
+    } while( i_lba <=
+      partition.i_start + dir.i_location + ( dir.i_length - 1 ) / DVD_LB_SIZE );
+
+    return 0;
+}
+
+
+/******************************************************************************
+ * UDFFindPartition: looks for a partition on the disc
+ * ---
+ *   partnum: number of the partition, starting at 0
+ *   part: structure to fill with the partition information
+ *   return 1 if partition found, 0 on error;
+ ******************************************************************************/
+static int UDFFindPartition( int i_part_nb, struct partition_s *p_partition )
+{
+    u8          pi_lb[DVD_LB_SIZE];
+    u8          pi_anchor[DVD_LB_SIZE];
+    u16         i_tag_id;
+    u32         i_lba;
+    u32         i_MVDS_location;
+    u32         i_MVDS_length;
+    u32         i_last_sector;
+    boolean_t   b_term;
+    boolean_t   b_vol_valid;
+    int         i;
+
+    /* Find Anchor */
+    i_last_sector = 0;
+    /* try #1, prime anchor */
+    i_lba = 256;    
+    b_term = 0;
+
+    /* Search anchor loop */
+    while( 1 )
+    {
+        if( UDFReadLB( p_partition->i_fd, i_lba, 1, pi_anchor ) )
+        {
+            UDFDescriptor( pi_anchor, &i_tag_id );
+        }
+        else
+        {
+            i_tag_id = 0;
+        }
+
+        if( i_tag_id != 2 )
+        {                
+            /* not an anchor? */
+            if( b_term )
+            {
+                /* final try failed */
+                return 0;
+            }
+
+            if( i_last_sector )
+            {
+                /* we already found the last sector
+                 * try #3, alternative backup anchor */
+                i_lba = i_last_sector;    
+            
+                /* but that's just about enough, then! */
+                b_term = 1;            
+            }
+            else
+            {
+                /* TODO: find last sector of the disc (this is optional) */
+                if( i_last_sector )
+                {
+                    /* try #2, backup anchor */
+                    i_lba = i_last_sector - 256;                
+                }
+                else
+                {
+                    /* unable to find last sector */
+                    return 0;
+                }
+            }
+        }
+        else
+        {
+            /* it is an anchor! continue... */
+            break;
+        }
+    }
+
+    /* main volume descriptor */
+    UDFExtentAD( &pi_anchor[16], &i_MVDS_length, &i_MVDS_location );
+  
+    p_partition->b_valid = 0;
+    b_vol_valid = 0;
+    p_partition->pi_volume_desc[0] = '\0';
+
+    i = 1;
+    /* Find Volume Descriptor */
+    do
+    {
+        i_lba = i_MVDS_location;
+
+        do
+        {
+            if( !UDFReadLB( p_partition->i_fd, i_lba++, 1, pi_lb ) )
+            {
+                i_tag_id = 0;
+            }
+            else
+            {
+                UDFDescriptor( pi_lb, &i_tag_id );
+            }
+
+            if( ( i_tag_id == 5 ) && ( !p_partition->b_valid ) )
+            {
+                /* Partition Descriptor */
+                UDFPartition( pi_lb,
+                              &p_partition->i_flags,
+                              &p_partition->i_number,
+                              p_partition->pi_contents,
+                              &p_partition->i_start,
+                              &p_partition->i_length );
+                p_partition->b_valid = ( i_part_nb == p_partition->i_number );
+            }
+            else if( ( i_tag_id == 6 ) && ( !b_vol_valid) )
+            {
+                /* Logical Volume Descriptor */
+                if( UDFLogVolume( pi_lb , p_partition->pi_volume_desc ) )
+                {  
+                /* TODO: sector size wrong! */
+                }
+                else
+                {
+                    b_vol_valid = 1;
+                }
+            }
+
+        } while( ( i_lba <= i_MVDS_location +
+                   ( i_MVDS_length - 1 ) / DVD_LB_SIZE )
+                 && ( i_tag_id != 8 )
+                 && ( ( !p_partition->b_valid ) || ( !b_vol_valid ) ) );
+    
+        if( ( !p_partition->b_valid ) || ( !b_vol_valid ) )
+        {
+            /* backup volume descriptor */
+            UDFExtentAD( &pi_anchor[24], &i_MVDS_length, &i_MVDS_location );
+        }
+    } while( i-- && ( ( !p_partition->b_valid ) || ( !b_vol_valid ) ) );
+
+    /* we only care for the partition, not the volume */
+    return( p_partition->b_valid);
+}
+
+
+/******************************************************************************
+ * UDFFindFile: looks for a file on the UDF disc/imagefile
+ * ---
+ * Path has to be the absolute pathname on the UDF filesystem,
+ * starting with '/'.
+ * returns absolute LB number, or 0 on error
+ ******************************************************************************/
+u32 UDFFindFile( int i_fd, char * psz_path )
+{
+    struct partition_s  partition;
+    struct ad_s         root_icb;
+    struct ad_s         file;
+    struct ad_s         icb;
+    u32                 i_lba;
+    u16                 i_tag_id;
+    u8                  pi_lb[DVD_LB_SIZE];
+    u8                  i_file_type;
+    char                psz_tokenline[DVD_LB_SIZE] = "";
+    char *              psz_token;
+    int                 i_partition;
+    strcat( psz_tokenline, psz_path );
+
+    /* Init file descriptor of UDF filesystem (== DVD) */
+    partition.i_fd = i_fd;
+
+    /* Find partition 0, standard partition for DVD-Video */
+    i_partition = 0;
+    if( !UDFFindPartition( i_partition, &partition ) )
+    {
+        intf_ErrMsg( "UDF: Partition 0 not found" );
+        return 0;
+    }
+  
+    /* Find root dir ICB */
+    i_lba = partition.i_start;
+
+    do
+    {
+        if( !UDFReadLB( i_fd, i_lba++, 1, pi_lb ) )
+        {
+            i_tag_id = 0;
+        }
+        else
+        {
+            UDFDescriptor( pi_lb, &i_tag_id );
+        }
+
+        if( i_tag_id == 256 )
+        {
+            /* File Set Descriptor */
+            UDFAD( &pi_lb[400], &root_icb, UDFADlong, partition );
+        }
+
+    } while( ( i_lba < partition.i_start + partition.i_length )
+          && ( i_tag_id != 8) && ( i_tag_id != 256 ) );
+
+    if( i_tag_id != 256 )
+    {
+        intf_ErrMsg( "UDF: Bad descriptor" );
+        return 0;
+    }
+    if( root_icb.i_partition != i_partition )
+    {
+        intf_ErrMsg( "UDF: Bad partition" );
+        return 0;
+    }
+  
+    /* Find root dir */
+    if( !UDFMapICB( root_icb, &i_file_type, &file, partition ) )
+    {
+        intf_ErrMsg( "UDF: Can't find root dir" );
+        return 0;
+    }
+
+    /* root dir should be dir */
+    if( i_file_type != 4 )
+    {
+        intf_ErrMsg( "UDF: Root dir error" );
+        return 0;
+    }
+
+    /* Tokenize filepath */
+    psz_token = strtok( psz_tokenline, "/" );
+    while( psz_token )
+    {
+        if( !UDFScanDir( file, psz_token, &icb, partition ) )
+        {
+            intf_ErrMsg( "UDF: Scan dir error" );
+            return 0;
+        }
+
+        if( !UDFMapICB ( icb, &i_file_type, &file, partition ) )
+        {
+            intf_ErrMsg( "UDF: ICB error" );
+            return 0;
+        }
+
+        psz_token = strtok( NULL, "/" );
+    }
+
+    return partition.i_start + file.i_location;
+}
index 037d2e5dccf317108f4e063b7fabebe0a1bed4c8..b3ed7a201ae4c3cee55d17015e63353c3f25d0a4 100644 (file)
@@ -2,7 +2,7 @@
  * dvd_udf.h: structures for udf filesystem tools.
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: dvd_udf.h,v 1.1 2001/02/15 21:03:27 stef Exp $
+ * $Id: dvd_udf.h,v 1.2 2001/02/18 01:42:05 stef Exp $
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
@@ -23,3 +23,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
+
+/*
+ * Fonctions in dvd_udf.c
+ */
+u32 UDFFindFile( int, char * );
index c8c02650f61b4a2e14eddac541dc6720ce6418cc..b2124b02e6349a2a1a0bbba67d549a2a39d75230 100644 (file)
@@ -10,7 +10,7 @@
  *  -dvd_udf to find files
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: input_dvd.c,v 1.12 2001/02/16 09:25:03 sam Exp $
+ * $Id: input_dvd.c,v 1.13 2001/02/18 01:42:05 stef Exp $
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
@@ -159,6 +159,16 @@ static int DVDCheckCSS( input_thread_t * p_input )
 #endif
 }
 
+/*****************************************************************************
+ * DVDSetRegion: initialize input data for title x, chapter y. It should
+ * be called for each user navigation request.
+ *****************************************************************************/
+static int DVDSetRegion( int i_title, int i_chapter )
+{
+    return 0;
+}
+
+
 /*****************************************************************************
  * DVDInit: initializes DVD structures
  *****************************************************************************/
@@ -182,7 +192,6 @@ static void DVDInit( input_thread_t * p_input )
     p_method->i_fd = p_input->i_handle;
     /* FIXME: read several packets once */
     p_method->i_read_once = 1; 
-    p_method->i_title = 0;
     p_method->b_encrypted = DVDCheckCSS( p_input );
 
     lseek( p_input->i_handle, 0, SEEK_SET );
@@ -194,6 +203,9 @@ static void DVDInit( input_thread_t * p_input )
     /* Ifo initialisation */
     p_method->ifo = IfoInit( p_input->i_handle );
 
+    /* FIXME: kludge */
+    p_method->i_title = p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb;
+
     /* CSS initialisation */
     if( p_method->b_encrypted )
     {
@@ -217,7 +229,7 @@ static void DVDInit( input_thread_t * p_input )
     IfoRead( &(p_method->ifo) );
     intf_WarnMsg( 3, "Ifo: Initialized" );
 
-    /* CSS title keys */
+    /* CSS title keys decryption */
     if( p_method->b_encrypted )
     {
 
@@ -260,8 +272,8 @@ static void DVDInit( input_thread_t * p_input )
     i_end_cell = 0;
 
     /* Loop on the number of vobs */
-    while( p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_cell].i_vob_id <=
-           p_method->ifo.p_vts[0].c_adt.i_vob_nb )
+    while( p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_cell].i_vob_id <=
+           p_method->ifo.p_vts[p_method->i_title].c_adt.i_vob_nb )
     {
         i_cell_1 = i_cell;
 
@@ -269,17 +281,17 @@ static void DVDInit( input_thread_t * p_input )
         do
         {
             i_cell++;
-            if( i_cell >= p_method->ifo.p_vts[0].c_adt.i_cell_nb )
+            if( i_cell >= p_method->ifo.p_vts[p_method->i_title].c_adt.i_cell_nb )
             {
                 break;
             }
         }
-        while( p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_cell-1].i_cell_id <
-               p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_cell].i_cell_id );
+        while( p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_cell-1].i_cell_id <
+               p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_cell].i_cell_id );
 
 
-        if( p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_cell-1].i_cell_id >
-            p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_end_cell].i_cell_id )
+        if( p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_cell-1].i_cell_id >
+            p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_end_cell].i_cell_id )
         {
             i_start_cell = i_cell_1;
             i_end_cell = i_cell - 1;
@@ -288,7 +300,7 @@ static void DVDInit( input_thread_t * p_input )
 
     /* The preceding does not work with all DVD, so we give the
      * last cell of the title as end */
-    i_end_cell = p_method->ifo.p_vts[0].c_adt.i_cell_nb - 1;
+    i_end_cell = p_method->ifo.p_vts[p_method->i_title].c_adt.i_cell_nb - 1;
 
     intf_WarnMsg( 2, "DVD: Start cell: %d End Cell: %d",
                                             i_start_cell, i_end_cell );
@@ -297,17 +309,17 @@ static void DVDInit( input_thread_t * p_input )
     p_method->i_end_cell = i_end_cell;
 
     /* start is : beginning of vts + offset to vobs + offset to vob x */
-    i_start = p_method->ifo.p_vts[0].i_pos + DVD_LB_SIZE *
-            ( p_method->ifo.p_vts[0].mat.i_tt_vobs_ssector +
-              p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_start_cell].i_ssector );
+    i_start = p_method->ifo.p_vts[p_method->i_title].i_pos + DVD_LB_SIZE *
+            ( p_method->ifo.p_vts[p_method->i_title].mat.i_tt_vobs_ssector +
+              p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_start_cell].i_ssector );
     p_method->i_start_byte = i_start;
                                                     
     i_start = lseek( p_input->i_handle, i_start, SEEK_SET );
     intf_WarnMsg( 3, "DVD: VOBstart at: %lld", i_start );
 
     i_size = (off_t)
-        ( p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_end_cell].i_esector -
-          p_method->ifo.p_vts[0].c_adt.p_cell_inf[i_start_cell].i_ssector + 1 )
+        ( p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_end_cell].i_esector -
+          p_method->ifo.p_vts[p_method->i_title].c_adt.p_cell_inf[i_start_cell].i_ssector + 1 )
         *DVD_LB_SIZE;
     intf_WarnMsg( 3, "DVD: stream size: %lld", i_size );
 
index 11c5b1823fdaca4417f367af604edcb6c7f0b9f6..7cfdbca1f67e02785656afb4fa8fd16e3bc84fd6 100644 (file)
@@ -27,7 +27,7 @@
 #define DVD_LB_SIZE 2048
 
 /*****************************************************************************
- * thread_dvd_data_t: extension of input_thread_t for DVD specificity
+ * thread_dvd_data_t: extension of input_thread_t for DVD specificity.
  *****************************************************************************/
 typedef struct thread_dvd_data_s
 {
@@ -36,7 +36,6 @@ typedef struct thread_dvd_data_s
     int                     i_read_once;        // NB of bytes read by DVDRead
     int                     i_title;            // Current Title
 
-    /* FIXME: include these in a struct */
     int                     i_start_byte;
     int                     i_start_cell;
     int                     i_end_cell;