[vlc-commits] access: cdrom: return TOC struct instead of only sectors

Francois Cartegnie git at videolan.org
Sat Jun 1 00:23:41 CEST 2019


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon May 27 17:13:21 2019 +0200| [890db4f7e7b04dc1c28bc3ba5eeebf76b102b9d0] | committer: Francois Cartegnie

access: cdrom: return TOC struct instead of only sectors

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=890db4f7e7b04dc1c28bc3ba5eeebf76b102b9d0
---

 modules/access/cdda.c                |  58 ++++----
 modules/access/vcd/cdrom.c           | 247 ++++++++++++++++++++++-------------
 modules/access/vcd/cdrom.h           |  32 ++++-
 modules/access/vcd/cdrom_internals.h |   5 +-
 modules/access/vcd/vcd.c             |  65 +++++----
 5 files changed, 253 insertions(+), 154 deletions(-)

diff --git a/modules/access/cdda.c b/modules/access/cdda.c
index d7974e2524..dca1461141 100644
--- a/modules/access/cdda.c
+++ b/modules/access/cdda.c
@@ -230,19 +230,19 @@ static int DemuxOpen(vlc_object_t *obj, vcddev_t *dev, unsigned track)
     /* Track number in input item */
     if (sys->start == (unsigned)-1 || sys->length == (unsigned)-1)
     {
-        int *sectors = NULL; /* Track sectors */
-        unsigned titles = ioctl_GetTracksMap(obj, dev, &sectors);
-
-        if (track > titles)
+        vcddev_toc_t *p_toc = ioctl_GetTOC(obj, dev, true);
+        if(p_toc == NULL)
+            goto error;
+        if (track > (unsigned)p_toc->i_tracks)
         {
-            msg_Err(obj, "invalid track number: %u/%u", track, titles);
-            free(sectors);
+            msg_Err(obj, "invalid track number: %u/%i", track, p_toc->i_tracks);
+            vcddev_toc_Free(p_toc);
             goto error;
         }
 
-        sys->start = sectors[track - 1];
-        sys->length = sectors[track] - sys->start;
-        free(sectors);
+        sys->start = p_toc->p_sectors[track - 1].i_lba;
+        sys->length = p_toc->p_sectors[track].i_lba - sys->start;
+        vcddev_toc_Free(p_toc);
     }
 
     es_format_t fmt;
@@ -271,8 +271,7 @@ error:
 typedef struct
 {
     vcddev_t    *vcddev;                            /* vcd device descriptor */
-    int         *p_sectors;                                 /* Track sectors */
-    int          titles;
+    vcddev_toc_t *p_toc;                            /* Tracks TOC */
     int          cdtextc;
     vlc_meta_t **cdtextv;
 #ifdef HAVE_LIBCDDB
@@ -281,7 +280,7 @@ typedef struct
 } access_sys_t;
 
 #ifdef HAVE_LIBCDDB
-static cddb_disc_t *GetCDDBInfo( vlc_object_t *obj, int i_titles, int *p_sectors )
+static cddb_disc_t *GetCDDBInfo( vlc_object_t *obj, const vcddev_toc_t *p_toc )
 {
     if( !var_InheritBool( obj, "metadata-network-access" ) )
     {
@@ -337,17 +336,17 @@ static cddb_disc_t *GetCDDBInfo( vlc_object_t *obj, int i_titles, int *p_sectors
     }
 
     int64_t i_length = 2000000; /* PreGap */
-    for( int i = 0; i < i_titles; i++ )
+    for( int i = 0; i < p_toc->i_tracks; i++ )
     {
         cddb_track_t *t = cddb_track_new();
-        cddb_track_set_frame_offset( t, p_sectors[i] + 150 );  /* Pregap offset */
+        cddb_track_set_frame_offset( t, p_toc->p_sectors[i].i_lba + 150 );  /* Pregap offset */
 
         cddb_disc_add_track( p_disc, t );
-        const int64_t i_size = ( p_sectors[i+1] - p_sectors[i] ) *
+        const int64_t i_size = ( p_toc->p_sectors[i+1].i_lba - p_toc->p_sectors[i].i_lba ) *
                                (int64_t)CDDA_DATA_SIZE;
         i_length += INT64_C(1000000) * i_size / 44100 / 4  ;
 
-        msg_Dbg( obj, "Track %i offset: %i", i, p_sectors[i] + 150 );
+        msg_Dbg( obj, "Track %i offset: %i", i, p_toc->p_sectors[i].i_lba + 150 );
     }
 
     msg_Dbg( obj, "Total length: %i", (int)(i_length/1000000) );
@@ -426,7 +425,7 @@ static void AccessGetMeta(stream_t *access, vlc_meta_t *meta)
         str = cddb_disc_get_artist(sys->cddb);
         if (NONEMPTY(str))
         {
-            for (int i = 0; i < sys->titles; i++)
+            for (int i = 0; i < sys->p_toc->i_tracks; i++)
             {
                 cddb_track_t *t = cddb_disc_get_track(sys->cddb, i);
                 if (t == NULL)
@@ -453,11 +452,12 @@ static void AccessGetMeta(stream_t *access, vlc_meta_t *meta)
 static int ReadDir(stream_t *access, input_item_node_t *node)
 {
     access_sys_t *sys = access->p_sys;
+    const vcddev_toc_t *p_toc = sys->p_toc;
 
     /* Build title table */
-    for (int i = 0; i < sys->titles; i++)
+    for (int i = 0; i < p_toc->i_tracks; i++)
     {
-        msg_Dbg(access, "track[%d] start=%d", i, sys->p_sectors[i]);
+        msg_Dbg(access, "track[%d] start=%d", i, p_toc->p_sectors[i].i_lba);
 
         /* Initial/default name */
         char *name;
@@ -467,7 +467,7 @@ static int ReadDir(stream_t *access, input_item_node_t *node)
 
         /* Create playlist items */
         const vlc_tick_t duration =
-            (vlc_tick_t)(sys->p_sectors[i + 1] - sys->p_sectors[i])
+            (vlc_tick_t)(p_toc->p_sectors[i + 1].i_lba - p_toc->p_sectors[i].i_lba)
             * CDDA_DATA_SIZE * CLOCK_FREQ / 44100 / 2 / 2;
 
         input_item_t *item = input_item_NewDisc(access->psz_url,
@@ -486,14 +486,14 @@ static int ReadDir(stream_t *access, input_item_node_t *node)
         }
 
         if (likely(asprintf(&opt, "cdda-first-sector=%i",
-                            sys->p_sectors[i]) != -1))
+                            p_toc->p_sectors[i].i_lba) != -1))
         {
             input_item_AddOption(item, opt, VLC_INPUT_OPTION_TRUSTED);
             free(opt);
         }
 
         if (likely(asprintf(&opt, "cdda-last-sector=%i",
-                            sys->p_sectors[i + 1]) != -1))
+                            p_toc->p_sectors[i + 1].i_lba) != -1))
         {
             input_item_AddOption(item, opt, VLC_INPUT_OPTION_TRUSTED);
             free(opt);
@@ -600,25 +600,24 @@ static int AccessOpen(vlc_object_t *obj, vcddev_t *dev)
     }
 
     sys->vcddev = dev;
-    sys->p_sectors = NULL;
-
-    sys->titles = ioctl_GetTracksMap(obj, dev, &sys->p_sectors);
-    if (sys->titles < 0)
+    sys->p_toc = ioctl_GetTOC(obj, dev, true);
+    if (sys->p_toc == NULL)
     {
         msg_Err(obj, "cannot count tracks");
         goto error;
     }
 
-    if (sys->titles == 0)
+    if (sys->p_toc->i_tracks == 0)
     {
         msg_Err(obj, "no audio tracks found");
+        vcddev_toc_Free(sys->p_toc);
         goto error;
     }
 
 #ifdef HAVE_LIBCDDB
     msg_Dbg(obj, "retrieving metadata with CDDB");
 
-    sys->cddb = GetCDDBInfo(obj, sys->titles, sys->p_sectors);
+    sys->cddb = GetCDDBInfo(obj, sys->p_toc);
     if (sys->cddb != NULL)
         msg_Dbg(obj, "disc ID: 0x%08x", cddb_disc_get_discid(sys->cddb));
     else
@@ -641,7 +640,6 @@ static int AccessOpen(vlc_object_t *obj, vcddev_t *dev)
     return VLC_SUCCESS;
 
 error:
-    free(sys->p_sectors);
     ioctl_Close(obj, dev);
     return VLC_EGENERIC;
 }
@@ -661,7 +659,7 @@ static void AccessClose(access_sys_t *sys)
         cddb_disc_destroy(sys->cddb);
 #endif
 
-    free(sys->p_sectors);
+    vcddev_toc_Free(sys->p_toc);
 }
 
 static int Open(vlc_object_t *obj)
diff --git a/modules/access/vcd/cdrom.c b/modules/access/vcd/cdrom.c
index 0639aeb734..8d7a461d3c 100644
--- a/modules/access/vcd/cdrom.c
+++ b/modules/access/vcd/cdrom.c
@@ -139,8 +139,8 @@ exit_free:
 #   error FIXME
 #endif
 
-#include "cdrom_internals.h"
 #include "cdrom.h"
+#include "cdrom_internals.h"
 
 /*****************************************************************************
  * ioctl_Open: Opens a VCD device or file and returns an opaque handle
@@ -164,6 +164,7 @@ vcddev_t *ioctl_Open( vlc_object_t *p_this, const char *psz_dev )
         return NULL;
     p_vcddev->i_vcdimage_handle = -1;
     p_vcddev->psz_dev = NULL;
+    memset( &p_vcddev->toc, 0, sizeof(p_vcddev->toc) );
     b_is_file = 1;
 
     /*
@@ -256,14 +257,15 @@ void ioctl_Close( vlc_object_t * p_this, vcddev_t *p_vcddev )
 }
 
 /*****************************************************************************
- * ioctl_GetTracksMap: Read the Table of Content, fill in the pp_sectors map
- *                     if pp_sectors is not null and return the number of
- *                     tracks available.
+ * ioctl_GetTOC: Read the Table of Content, fill in the p_sectors map
+ *               if b_fill_sector_info is true.
  *****************************************************************************/
-int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
-                        int **pp_sectors )
+vcddev_toc_t * ioctl_GetTOC( vlc_object_t *p_this, const vcddev_t *p_vcddev,
+                             bool b_fill_sectorinfo )
 {
-    int i_tracks = 0;
+    vcddev_toc_t *p_toc = calloc(1, sizeof(*p_toc));
+    if(!p_toc)
+        return NULL;
 
     if( p_vcddev->i_vcdimage_handle != -1 )
     {
@@ -271,18 +273,22 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
          *  vcd image mode
          */
 
-        i_tracks = p_vcddev->i_tracks;
+        *p_toc = p_vcddev->toc;
+        p_toc->p_sectors = NULL;
 
-        if( pp_sectors )
+        if( b_fill_sectorinfo )
         {
-            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
-            if( *pp_sectors == NULL )
-                return 0;
-            memcpy( *pp_sectors, p_vcddev->p_sectors,
-                    (i_tracks + 1) * sizeof(**pp_sectors) );
+            p_toc->p_sectors = calloc( p_toc->i_tracks + 1, sizeof(*p_toc->p_sectors) );
+            if( p_toc->p_sectors == NULL )
+            {
+                free( p_toc );
+                return NULL;
+            }
+            memcpy( p_toc->p_sectors, p_vcddev->toc.p_sectors,
+                    (p_toc->i_tracks + 1) * sizeof(*p_toc->p_sectors) );
         }
 
-        return i_tracks;
+        return p_toc;
     }
     else
     {
@@ -299,28 +305,33 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
         if( ( pTOC = darwin_getTOC( p_this, p_vcddev ) ) == NULL )
         {
             msg_Err( p_this, "failed to get the TOC" );
-            return 0;
+            vcddev_toc_Free( p_toc );
+            return NULL;
         }
 
         i_descriptors = CDTOCGetDescriptorCount( pTOC );
-        i_tracks = darwin_getNumberOfTracks( pTOC, i_descriptors );
+        p_toc->i_tracks = darwin_getNumberOfTracks( pTOC, i_descriptors,
+                                                    &p_toc->i_first_track,
+                                                    &p_toc->i_last_track );
 
-        if( pp_sectors )
+        if( b_fill_sectorinfo )
         {
             int i, i_leadout = -1;
             CDTOCDescriptor *pTrackDescriptors;
             u_char track;
 
-            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
-            if( *pp_sectors == NULL )
+            p_toc->p_sectors = calloc( p_toc->i_tracks + 1,
+                                       sizeof(*p_toc->p_sectors) );
+            if( p_toc->p_sectors == NULL )
             {
+                vcddev_toc_Free( p_toc );
                 darwin_freeTOC( pTOC );
-                return 0;
+                return NULL;
             }
 
             pTrackDescriptors = pTOC->descriptors;
 
-            for( i_tracks = 0, i = 0; i < i_descriptors; i++ )
+            for( p_toc->i_tracks = 0, i = 0; i < i_descriptors; i++ )
             {
                 track = pTrackDescriptors[i].point;
 
@@ -330,20 +341,21 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
                 if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO )
                     continue;
 
-                (*pp_sectors)[i_tracks++] =
+                p_toc->p_sectors[p_toc->i_tracks].i_control = pTrackDescriptors[i].control;
+                p_toc->p_sectors[p_toc->i_tracks++].i_lba =
                     CDConvertMSFToLBA( pTrackDescriptors[i].p );
             }
 
             if( i_leadout == -1 )
             {
                 msg_Err( p_this, "leadout not found" );
-                free( *pp_sectors );
+                vcddev_toc_Free( p_toc );
                 darwin_freeTOC( pTOC );
-                return 0;
+                return NULL;
             }
 
             /* set leadout sector */
-            (*pp_sectors)[i_tracks] =
+            p_toc->p_sectors[p_toc->i_tracks].i_lba =
                 CDConvertMSFToLBA( pTrackDescriptors[i_leadout].p );
         }
 
@@ -358,24 +370,31 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
                              &dwBytesReturned, NULL ) == 0 )
         {
             msg_Err( p_this, "could not read TOCHDR" );
-            return 0;
+            vcddev_toc_Free( p_toc );
+            return NULL;
         }
 
-        i_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1;
+        p_toc->i_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1;
+        p_toc->i_first_track = cdrom_toc.FirstTrack;
+        p_toc->i_last_track = cdrom_toc.LastTrack;
 
-        if( pp_sectors )
+        if( b_fill_sectorinfo )
         {
-            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
-            if( *pp_sectors == NULL )
-                return 0;
+            p_toc->p_sectors = calloc( p_toc->i_tracks + 1, sizeof(p_toc->p_sectors) );
+            if( p_toc->p_sectors == NULL )
+            {
+                vcddev_toc_Free( p_toc );
+                return NULL;
+            }
 
-            for( int i = 0 ; i <= i_tracks ; i++ )
+            for( int i = 0 ; i <= p_toc->i_tracks ; i++ )
             {
-                (*pp_sectors)[ i ] = MSF_TO_LBA2(
+                p_toc->p_sectors[ i ].i_control = cdrom_toc.TrackData[i].Control;
+                p_toc->p_sectors[ i ].i_lba = MSF_TO_LBA2(
                                            cdrom_toc.TrackData[i].Address[1],
                                            cdrom_toc.TrackData[i].Address[2],
                                            cdrom_toc.TrackData[i].Address[3] );
-                msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]);
+                msg_Dbg( p_this, "p_sectors: %i, %i", i, p_toc->p_sectors[i].i_lba);
              }
         }
 
@@ -397,19 +416,24 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
             return 0;
         }
 
-        i_tracks = tochdr.last_track - tochdr.first_track + 1;
+        p_toc->i_tracks = tochdr.last_track - tochdr.first_track + 1;
+        p_toc->i_first_track = tochdr.first_track;
+        p_toc->i_last_track = tochdr.last_track;
 
-        if( pp_sectors )
+        if( b_fill_sectorinfo )
         {
             cdrom_get_track_t get_track = {{'C', 'D', '0', '1'}, };
             cdrom_track_t track;
             int i;
 
-            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
-            if( *pp_sectors == NULL )
-                return 0;
+            p_toc->p_sectors = calloc( p_toc->i_tracks + 1, sizeof(*p_toc->p_sectors) );
+            if( *p_toc->p_sectors == NULL )
+            {
+                vcddev_toc_Free( p_toc );
+                return NULL;
+            }
 
-            for( i = 0 ; i < i_tracks ; i++ )
+            for( i = 0 ; i < p_toc->i_tracks ; i++ )
             {
                 get_track.track = tochdr.first_track + i;
                 rc = DosDevIOCtl( p_vcddev->hcd, IOCTL_CDROMAUDIO,
@@ -420,22 +444,23 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
                 {
                     msg_Err( p_this, "could not read %d track",
                              get_track.track );
-                    return 0;
+                    vcddev_toc_Free( p_toc );
+                    return NULL;
                 }
 
-                (*pp_sectors)[ i ] = MSF_TO_LBA2(
+                p_toc->p_sectors[ i ].i_lba = MSF_TO_LBA2(
                                        track.start.minute,
                                        track.start.second,
                                        track.start.frame );
-                msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]);
+                msg_Dbg( p_this, "p_sectors: %i, %i", i, p_toc->p_sectors[i].i_lba);
             }
 
             /* for lead-out track */
-            (*pp_sectors)[ i ] = MSF_TO_LBA2(
+            p_toc->p_sectors[ i ].i_lba = MSF_TO_LBA2(
                                    tochdr.lead_out.minute,
                                    tochdr.lead_out.second,
                                    tochdr.lead_out.frame );
-            msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]);
+            msg_Dbg( p_this, "p_sectors: %i, %i", i, p_toc->p_sectors[i].i_lba);
         }
 
 #elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H ) \
@@ -447,27 +472,33 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
             == -1 )
         {
             msg_Err( p_this, "could not read TOCHDR" );
-            return 0;
+            vcddev_toc_Free( p_toc );
+            return NULL;
         }
 
-        i_tracks = tochdr.ending_track - tochdr.starting_track + 1;
+        p_toc->i_tracks = tochdr.ending_track - tochdr.starting_track + 1;
+        p_toc->i_first_track = tochdr.starting_track;
+        p_toc->i_last_track = tochdr.ending_track;
 
-        if( pp_sectors )
+        if( b_fill_sectorinfo )
         {
-             *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
-             if( *pp_sectors == NULL )
-                 return 0;
+             p_toc->p_sectors = calloc( p_toc->i_tracks + 1, sizeof(*p_toc->p_sectors) );
+             if( p_toc->p_sectors == NULL )
+             {
+                 vcddev_toc_Free( p_toc );
+                 return NULL;
+             }
 
              toc_entries.address_format = CD_LBA_FORMAT;
              toc_entries.starting_track = 0;
-             toc_entries.data_len = ( i_tracks + 1 ) *
+             toc_entries.data_len = ( p_toc->i_tracks + 1 ) *
                                         sizeof( struct cd_toc_entry );
              toc_entries.data = (struct cd_toc_entry *)
                                     malloc( toc_entries.data_len );
              if( toc_entries.data == NULL )
              {
-                 free( *pp_sectors );
-                 return 0;
+                 vcddev_toc_Free( p_toc );
+                 return NULL;
              }
 
              /* Read the TOC */
@@ -475,19 +506,19 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
                         &toc_entries ) == -1 )
              {
                  msg_Err( p_this, "could not read the TOC" );
-                 free( *pp_sectors );
                  free( toc_entries.data );
-                 return 0;
+                 vcddev_toc_Free( p_toc );
+                 return NULL;
              }
 
              /* Fill the p_sectors structure with the track/sector matches */
-             for( int i = 0 ; i <= i_tracks ; i++ )
+             for( int i = 0 ; i <= p_toc->i_tracks ; i++ )
              {
 #if defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H )
                  /* FIXME: is this ok? */
-                 (*pp_sectors)[ i ] = toc_entries.data[i].addr.lba;
+                 p_toc->p_sectors[ i ].i_lba = toc_entries.data[i].addr.lba;
 #else
-                 (*pp_sectors)[ i ] = ntohl( toc_entries.data[i].addr.lba );
+                 p_toc->p_sectors[ i ].i_lba = ntohl( toc_entries.data[i].addr.lba );
 #endif
              }
         }
@@ -500,38 +531,46 @@ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
             == -1 )
         {
             msg_Err( p_this, "could not read TOCHDR" );
-            return 0;
+            free( p_toc );
+            return NULL;
         }
 
-        i_tracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
+        p_toc->i_tracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
+        p_toc->i_first_track = tochdr.cdth_trk0;
+        p_toc->i_last_track = tochdr.cdth_trk1;
 
-        if( pp_sectors )
+        if( b_fill_sectorinfo )
         {
-            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
-            if( *pp_sectors == NULL )
-                return 0;
+            p_toc->p_sectors = calloc( p_toc->i_tracks + 1, sizeof(*p_toc->p_sectors) );
+            if( p_toc->p_sectors == NULL )
+            {
+                free( p_toc );
+                return NULL;
+            }
 
             /* Fill the p_sectors structure with the track/sector matches */
-            for( int i = 0 ; i <= i_tracks ; i++ )
+            for( int i = 0 ; i <= p_toc->i_tracks ; i++ )
             {
                 tocent.cdte_format = CDROM_LBA;
                 tocent.cdte_track =
-                    ( i == i_tracks ) ? CDROM_LEADOUT : tochdr.cdth_trk0 + i;
+                    ( i == p_toc->i_tracks ) ? CDROM_LEADOUT : tochdr.cdth_trk0 + i;
 
                 if( ioctl( p_vcddev->i_device_handle, CDROMREADTOCENTRY,
                            &tocent ) == -1 )
                 {
                     msg_Err( p_this, "could not read TOCENTRY" );
-                    free( *pp_sectors );
-                    return 0;
+                    free( p_toc->p_sectors );
+                    free( p_toc );
+                    return NULL;
                 }
 
-                (*pp_sectors)[ i ] = tocent.cdte_addr.lba;
+                p_toc->p_sectors[ i ].i_lba = tocent.cdte_addr.lba;
+                p_toc->p_sectors[ i ].i_control = tocent.cdte_ctrl;
             }
         }
 #endif
 
-        return i_tracks;
+        return p_toc;
     }
 }
 
@@ -766,7 +805,7 @@ static int OpenVCDImage( vlc_object_t * p_this, const char *psz_dev,
     char *psz_vcdfile = NULL;
     char *psz_cuefile = NULL;
     FILE *cuefile     = NULL;
-    int *p_sectors    = NULL;
+    vcddev_toc_t *p_toc = &p_vcddev->toc;
     char line[1024];
     bool b_found      = false;
 
@@ -857,9 +896,9 @@ static int OpenVCDImage( vlc_object_t * p_this, const char *psz_dev,
 
     /* Try to parse the i_tracks and p_sectors info so we can just forget
      * about the cuefile */
-    size_t i_tracks = 0;
+    p_toc->i_tracks = 0;
 
-    while( fgets( line, 1024, cuefile ) && i_tracks < INT_MAX-1 )
+    while( fgets( line, 1024, cuefile ) && p_toc->i_tracks < INT_MAX-1 )
     {
         /* look for a TRACK line */
         char psz_dummy[10];
@@ -875,35 +914,42 @@ static int OpenVCDImage( vlc_object_t * p_this, const char *psz_dev,
                          &i_min, &i_sec, &i_frame ) != 4) || (i_num != 1) )
                 continue;
 
-            int *buf = realloc (p_sectors, (i_tracks + 1) * sizeof (*buf));
+            vcddev_sector_t *buf = realloc (p_toc->p_sectors,
+                                            (p_toc->i_tracks + 1) * sizeof (*buf));
             if (buf == NULL)
                 goto error;
-            p_sectors = buf;
-            p_sectors[i_tracks] = MSF_TO_LBA(i_min, i_sec, i_frame);
+            p_toc->p_sectors = buf;
+            p_toc->p_sectors[p_toc->i_tracks].i_lba = MSF_TO_LBA(i_min, i_sec, i_frame);
+            p_toc->p_sectors[p_toc->i_tracks].i_control = 0x00;
             msg_Dbg( p_this, "vcd track %i begins at sector:%i",
-                     (int)i_tracks, (int)p_sectors[i_tracks] );
-            i_tracks++;
+                     p_toc->i_tracks, p_toc->p_sectors[p_toc->i_tracks].i_lba );
+            p_toc->i_tracks++;
             break;
         }
     }
 
     /* fill in the last entry */
-    int *buf = realloc (p_sectors, (i_tracks + 1) * sizeof (*buf));
+    vcddev_sector_t *buf = realloc (p_toc->p_sectors,
+                                    (p_toc->i_tracks + 1) * sizeof (*buf));
     if (buf == NULL)
         goto error;
-    p_sectors = buf;
-    p_sectors[i_tracks] = lseek(p_vcddev->i_vcdimage_handle, 0, SEEK_END)
-                                 / VCD_SECTOR_SIZE;
+    p_toc->p_sectors = buf;
+    p_toc->p_sectors[p_toc->i_tracks].i_lba =
+            lseek(p_vcddev->i_vcdimage_handle, 0, SEEK_END) / VCD_SECTOR_SIZE;
+    p_toc->p_sectors[p_toc->i_tracks].i_control = 0x00;
     msg_Dbg( p_this, "vcd track %i, begins at sector:%i",
-             (int)i_tracks, (int)p_sectors[i_tracks] );
-    p_vcddev->i_tracks = ++i_tracks;
-    p_vcddev->p_sectors = p_sectors;
-    p_sectors = NULL;
+             p_toc->i_tracks, p_toc->p_sectors[p_toc->i_tracks].i_lba );
+    p_toc->i_tracks++;
+    p_toc->i_first_track = 1;
+    p_toc->i_last_track = p_toc->i_tracks;
     i_ret = 0;
+    goto end;
 
 error:
+    free( p_toc->p_sectors );
+    memset( p_toc, 0, sizeof(*p_toc) );
+end:
     if( cuefile ) fclose( cuefile );
-    free( p_sectors );
     free( psz_cuefile );
     free( psz_vcdfile );
 
@@ -921,7 +967,7 @@ static void CloseVCDImage( vlc_object_t * p_this, vcddev_t *p_vcddev )
     else
         return;
 
-    free( p_vcddev->p_sectors );
+    free( p_vcddev->toc.p_sectors );
 }
 
 #if defined( __APPLE__ )
@@ -1028,11 +1074,16 @@ static CDTOC *darwin_getTOC( vlc_object_t * p_this, const vcddev_t *p_vcddev )
 
 /****************************************************************************
  * darwin_getNumberOfTracks: get number of tracks in TOC
+ *                           and first and last CDDA ones
  ****************************************************************************/
-static int darwin_getNumberOfTracks( CDTOC *pTOC, int i_descriptors )
+static int darwin_getNumberOfTracks( CDTOC *pTOC, int i_descriptors,
+                                     int *pi_first_track,
+                                     int *pi_last_track )
 {
     u_char track;
     int i, i_tracks = 0;
+    int i_min = CD_MAX_TRACK_NO;
+    int i_max = CD_MIN_TRACK_NO;
     CDTOCDescriptor *pTrackDescriptors = NULL;
 
     pTrackDescriptors = (CDTOCDescriptor *)pTOC->descriptors;
@@ -1044,9 +1095,23 @@ static int darwin_getNumberOfTracks( CDTOC *pTOC, int i_descriptors )
         if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO )
             continue;
 
+        if( pTrackDescriptors[i].adr == 0x01 /* kCDSectorTypeCDDA */ )
+        {
+            i_min = __MIN(i_min, track);
+            i_max = __MAX(i_max, track);
+        }
+
         i_tracks++;
     }
 
+    if( i_max < i_min )
+        *pi_first_track = *pi_last_track = 0;
+    else
+    {
+        *pi_first_track = i_min;
+        *pi_last_track = i_max;
+    }
+
     return( i_tracks );
 }
 #endif /* __APPLE__ */
diff --git a/modules/access/vcd/cdrom.h b/modules/access/vcd/cdrom.h
index 18cb5563ae..fe4dc34f4d 100644
--- a/modules/access/vcd/cdrom.h
+++ b/modules/access/vcd/cdrom.h
@@ -73,6 +73,36 @@ static inline int MSF_TO_LBA2(uint8_t min, uint8_t sec, uint8_t frame)
     (uint8_t)((uint8_t)(0xf & (uint8_t)i)+((uint8_t)10*((uint8_t)i >> 4)))
 
 typedef struct vcddev_s vcddev_t;
+typedef struct
+{
+    int i_lba;
+    int i_control;
+} vcddev_sector_t;
+
+typedef struct
+{
+    int i_tracks;
+    vcddev_sector_t *p_sectors;
+    int i_first_track;
+    int i_last_track;
+} vcddev_toc_t;
+
+static inline vcddev_toc_t * vcddev_toc_New( void )
+{
+    return calloc(1, sizeof(vcddev_toc_t));
+}
+
+static inline void vcddev_toc_Reset( vcddev_toc_t *toc )
+{
+    free(toc->p_sectors);
+    memset(toc, 0, sizeof(*toc));
+}
+
+static inline void vcddev_toc_Free( vcddev_toc_t *toc )
+{
+    free(toc->p_sectors);
+    free(toc);
+}
 
 /*****************************************************************************
  * structure to store minute/second/frame locations
@@ -110,7 +140,7 @@ typedef struct entries_sect_s
  *****************************************************************************/
 vcddev_t *ioctl_Open         ( vlc_object_t *, const char * );
 void      ioctl_Close        ( vlc_object_t *, vcddev_t * );
-int       ioctl_GetTracksMap ( vlc_object_t *, const vcddev_t *, int ** );
+vcddev_toc_t * ioctl_GetTOC  ( vlc_object_t *, const vcddev_t *, bool );
 int       ioctl_ReadSectors  ( vlc_object_t *, const vcddev_t *,
                                int, uint8_t *, int, int );
 
diff --git a/modules/access/vcd/cdrom_internals.h b/modules/access/vcd/cdrom_internals.h
index 3b8e0a1f9c..6178372496 100644
--- a/modules/access/vcd/cdrom_internals.h
+++ b/modules/access/vcd/cdrom_internals.h
@@ -30,8 +30,7 @@ struct vcddev_s
 
     /* Section used in vcd image mode */
     int    i_vcdimage_handle;                   /* vcd image file descriptor */
-    int    i_tracks;                          /* number of tracks of the vcd */
-    int    *p_sectors;                           /* tracks layout on the vcd */
+    vcddev_toc_t toc;                           /* tracks layout on the vcd */
 
     /* Section used in vcd device mode */
 
@@ -180,7 +179,7 @@ static void   CloseVCDImage( vlc_object_t *, struct vcddev_s * );
 
 #if defined( __APPLE__ )
 static CDTOC *darwin_getTOC( vlc_object_t *, const struct vcddev_s * );
-static int    darwin_getNumberOfTracks( CDTOC *, int );
+static int    darwin_getNumberOfTracks( CDTOC *, int, int *, int * );
 
 #elif defined( _WIN32 )
 static int    win32_vcd_open( vlc_object_t *, const char *, struct vcddev_s *);
diff --git a/modules/access/vcd/vcd.c b/modules/access/vcd/vcd.c
index 86fd68004c..40c2000448 100644
--- a/modules/access/vcd/vcd.c
+++ b/modules/access/vcd/vcd.c
@@ -68,7 +68,8 @@ typedef struct
     uint64_t    offset;
 
     /* Title infos */
-    int           i_titles;
+    vcddev_toc_t *p_toc;
+
     struct
     {
         uint64_t *seekpoints;
@@ -76,9 +77,7 @@ typedef struct
     } titles[99];                        /* No more that 99 track in a vcd ? */
     int         i_current_title;
     unsigned    i_current_seekpoint;
-
     int         i_sector;                                  /* Current Sector */
-    int         *p_sectors;                                 /* Track sectors */
 } access_sys_t;
 
 static block_t *Block( stream_t *, bool * );
@@ -151,26 +150,28 @@ static int Open( vlc_object_t *p_this )
         p_sys->titles[i].seekpoints = NULL;
 
     /* We read the Table Of Content information */
-    p_sys->i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access),
-                                          p_sys->vcddev, &p_sys->p_sectors );
-    if( p_sys->i_titles < 0 )
+    p_sys->p_toc = ioctl_GetTOC( VLC_OBJECT(p_access), p_sys->vcddev, true );
+    if( p_sys->p_toc == NULL )
     {
         msg_Err( p_access, "unable to count tracks" );
         goto error;
     }
-    else if( p_sys->i_titles <= 1 )
+    else if( p_sys->p_toc->i_tracks <= 1 )
     {
+        vcddev_toc_Free( p_sys->p_toc );
+        p_sys->p_toc = NULL;
         msg_Err( p_access, "no movie tracks found" );
         goto error;
     }
 
     /* The first title isn't usable */
-    p_sys->i_titles--;
+#define USABLE_TITLES(a) (a - 1)
+    //p_sys->i_titles--;
 
-    for( int i = 0; i < p_sys->i_titles; i++ )
+    for( int i = 0; i < USABLE_TITLES(p_sys->p_toc->i_tracks); i++ )
     {
-        msg_Dbg( p_access, "title[%d] start=%d", i, p_sys->p_sectors[1+i] );
-        msg_Dbg( p_access, "title[%d] end=%d", i, p_sys->p_sectors[i+2] );
+        msg_Dbg( p_access, "title[%d] start=%d", i, p_sys->p_toc->p_sectors[1+i].i_lba );
+        msg_Dbg( p_access, "title[%d] end=%d", i, p_sys->p_toc->p_sectors[i+2].i_lba );
     }
 
     /* Map entry points into chapters */
@@ -180,12 +181,12 @@ static int Open( vlc_object_t *p_this )
     }
 
     /* Starting title/chapter and sector */
-    if( i_title >= p_sys->i_titles )
+    if( i_title > USABLE_TITLES(p_sys->p_toc->i_tracks) )
         i_title = 0;
     if( (unsigned)i_chapter >= p_sys->titles[i_title].count )
         i_chapter = 0;
 
-    p_sys->i_sector = p_sys->p_sectors[1+i_title];
+    p_sys->i_sector = p_sys->p_toc->p_sectors[1+i_title].i_lba;
     if( i_chapter > 0 )
         p_sys->i_sector += p_sys->titles[i_title].seekpoints[i_chapter]
                            / VCD_DATA_SIZE;
@@ -198,7 +199,7 @@ static int Open( vlc_object_t *p_this )
 
     p_sys->i_current_title = i_title;
     p_sys->i_current_seekpoint = i_chapter;
-    p_sys->offset = (uint64_t)(p_sys->i_sector - p_sys->p_sectors[1+i_title]) *
+    p_sys->offset = (uint64_t)(p_sys->i_sector - p_sys->p_toc->p_sectors[1+i_title].i_lba) *
                                VCD_DATA_SIZE;
 
     return VLC_SUCCESS;
@@ -220,6 +221,8 @@ static void Close( vlc_object_t *p_this )
     for( size_t i = 0; i < ARRAY_SIZE(p_sys->titles); i++ )
         free( p_sys->titles[i].seekpoints );
 
+    vcddev_toc_Free( p_sys->p_toc );
+
     ioctl_Close( p_this, p_sys->vcddev );
     free( p_sys );
 }
@@ -247,8 +250,8 @@ static int Control( stream_t *p_access, int i_query, va_list args )
             int i = p_sys->i_current_title;
 
             *va_arg( args, uint64_t * ) =
-                (p_sys->p_sectors[i + 2] - p_sys->p_sectors[i + 1])
-                               * (uint64_t)VCD_DATA_SIZE;
+                (p_sys->p_toc->p_sectors[i + 2].i_lba -
+                 p_sys->p_toc->p_sectors[i + 1].i_lba) * (uint64_t)VCD_DATA_SIZE;
             break;
         }
 
@@ -265,11 +268,12 @@ static int Control( stream_t *p_access, int i_query, va_list args )
         case STREAM_GET_TITLE_INFO:
             ppp_title = va_arg( args, input_title_t*** );
             /* Duplicate title infos */
-            *ppp_title = vlc_alloc( p_sys->i_titles, sizeof(input_title_t *) );
+            *ppp_title = vlc_alloc( USABLE_TITLES(p_sys->p_toc->i_tracks),
+                                    sizeof(input_title_t *) );
             if (!*ppp_title)
                 return VLC_ENOMEM;
-            *va_arg( args, int* ) = p_sys->i_titles;
-            for( int i = 0; i < p_sys->i_titles; i++ )
+            *va_arg( args, int* ) = USABLE_TITLES(p_sys->p_toc->i_tracks);
+            for( int i = 0; i < USABLE_TITLES(p_sys->p_toc->i_tracks); i++ )
                 (*ppp_title)[i] = vlc_input_title_New();
             break;
 
@@ -296,7 +300,7 @@ static int Control( stream_t *p_access, int i_query, va_list args )
                 p_sys->i_current_seekpoint = 0;
 
                 /* Next sector to read */
-                p_sys->i_sector = p_sys->p_sectors[1+i];
+                p_sys->i_sector = p_sys->p_toc->p_sectors[1+i].i_lba;
             }
             break;
         }
@@ -310,11 +314,11 @@ static int Control( stream_t *p_access, int i_query, va_list args )
             {
                 p_sys->i_current_seekpoint = i;
 
-                p_sys->i_sector = p_sys->p_sectors[1 + i_title] +
+                p_sys->i_sector = p_sys->p_toc->p_sectors[1 + i_title].i_lba +
                     p_sys->titles[i_title].seekpoints[i] / VCD_DATA_SIZE;
 
                 p_sys->offset = (uint64_t)(p_sys->i_sector -
-                    p_sys->p_sectors[1 + i_title]) * VCD_DATA_SIZE;
+                    p_sys->p_toc->p_sectors[1 + i_title].i_lba) * VCD_DATA_SIZE;
             }
             break;
         }
@@ -331,13 +335,14 @@ static int Control( stream_t *p_access, int i_query, va_list args )
 static block_t *Block( stream_t *p_access, bool *restrict eof )
 {
     access_sys_t *p_sys = p_access->p_sys;
+    const vcddev_toc_t *p_toc = p_sys->p_toc;
     int i_blocks = VCD_BLOCKS_ONCE;
     block_t *p_block;
 
     /* Check end of title */
-    while( p_sys->i_sector >= p_sys->p_sectors[p_sys->i_current_title + 2] )
+    while( p_sys->i_sector >= p_toc->p_sectors[p_sys->i_current_title + 2].i_lba )
     {
-        if( p_sys->i_current_title + 2 >= p_sys->i_titles )
+        if( p_sys->i_current_title + 2 >= USABLE_TITLES(p_toc->i_tracks) )
         {
             *eof = true;
             return NULL;
@@ -350,9 +355,9 @@ static block_t *Block( stream_t *p_access, bool *restrict eof )
 
     /* Don't read after the end of a title */
     if( p_sys->i_sector + i_blocks >=
-        p_sys->p_sectors[p_sys->i_current_title + 2] )
+        p_toc->p_sectors[p_sys->i_current_title + 2].i_lba )
     {
-        i_blocks = p_sys->p_sectors[p_sys->i_current_title + 2 ] - p_sys->i_sector;
+        i_blocks = p_toc->p_sectors[p_sys->i_current_title + 2 ].i_lba - p_sys->i_sector;
     }
 
     /* Do the actual reading */
@@ -403,12 +408,13 @@ static block_t *Block( stream_t *p_access, bool *restrict eof )
 static int Seek( stream_t *p_access, uint64_t i_pos )
 {
     access_sys_t *p_sys = p_access->p_sys;
+    const vcddev_toc_t *p_toc = p_sys->p_toc;
     int i_title = p_sys->i_current_title;
     unsigned i_seekpoint;
 
     /* Next sector to read */
     p_sys->offset = i_pos;
-    p_sys->i_sector = i_pos / VCD_DATA_SIZE + p_sys->p_sectors[i_title + 1];
+    p_sys->i_sector = i_pos / VCD_DATA_SIZE + p_toc->p_sectors[i_title + 1].i_lba;
 
     /* Update current seekpoint */
     for( i_seekpoint = 0; i_seekpoint < p_sys->titles[i_title].count; i_seekpoint++ )
@@ -433,6 +439,7 @@ static int Seek( stream_t *p_access, uint64_t i_pos )
 static int EntryPoints( stream_t *p_access )
 {
     access_sys_t *p_sys = p_access->p_sys;
+    const vcddev_toc_t *p_toc = p_sys->p_toc;
     uint8_t      sector[VCD_DATA_SIZE];
 
     entries_sect_t entries;
@@ -469,7 +476,7 @@ static int EntryPoints( stream_t *p_access )
                           BCD_TO_BIN( entries.entry[i].msf.second ),
                           BCD_TO_BIN( entries.entry[i].msf.frame  ) ));
         if( i_title < 0 ) continue;   /* Should not occur */
-        if( i_title >= p_sys->i_titles ) continue;
+        if( i_title >= USABLE_TITLES(p_toc->i_tracks) ) continue;
 
         msg_Dbg( p_access, "Entry[%d] title=%d sector=%d",
                  i, i_title, i_sector );
@@ -478,7 +485,7 @@ static int EntryPoints( stream_t *p_access )
             p_sys->titles[i_title].seekpoints,
             sizeof( uint64_t ) * (p_sys->titles[i_title].count + 1) );
         p_sys->titles[i_title].seekpoints[p_sys->titles[i_title].count++] =
-            (i_sector - p_sys->p_sectors[i_title+1]) * VCD_DATA_SIZE;
+            (i_sector - p_toc->p_sectors[i_title+1].i_lba) * VCD_DATA_SIZE;
     }
 
     return VLC_SUCCESS;



More information about the vlc-commits mailing list