[vlc-commits] access: cdda: fix audio/data mixed mode

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


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri May 31 18:04:40 2019 +0200| [f548e999c9761b23e41dd7945640c62414c2553d] | committer: Francois Cartegnie

access: cdda: fix audio/data mixed mode

best way to kill your speakers

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

 NEWS                       |   1 +
 modules/access/cdda.c      | 105 ++++++++++++++++++++++++++++++++++++++++-----
 modules/access/vcd/cdrom.h |   3 ++
 3 files changed, 99 insertions(+), 10 deletions(-)

diff --git a/NEWS b/NEWS
index a90762a649..554538d9a0 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,7 @@ Access:
  * Enable SMB2 / SMB3 support on mobile ports with libsmb2
  * Added support for the RIST (Reliable Internet Stream Transport) Protocol
  * Added avaudiocapture module as a replacement for qtsound, which is removed now
+ * Audio CD data tracks are now correctly detected and skipped
 
 Access output:
  * Added support for the RIST (Reliable Internet Stream Transport) Protocol
diff --git a/modules/access/cdda.c b/modules/access/cdda.c
index dca1461141..69e4cb6acb 100644
--- a/modules/access/cdda.c
+++ b/modules/access/cdda.c
@@ -211,6 +211,67 @@ static int DemuxControl(demux_t *demux, int query, va_list args)
     return VLC_SUCCESS;
 }
 
+/*
+ * Check for Mixed Audio/CDROM data
+ *
+ * ioctl will return first track # and last track # from last TOC
+ * (this could start > 1..  but where's the case ?)
+ *
+ * vcdev_toc stores i_tracks as the number of STORED sectors info,
+ * this is last - first track, plus one (the LEADOUT one)
+ *
+ * tracks can be DATA in mixed data/audio mode (CDROM spec, not CDDA)
+ * and this is control flag (Subcode Channel Q)
+ *
+ * first: 1 last 13
+ * track:   1 lba:         0 (        0) 00:02:00 adr: 1 control: 0 mode: -1
+ * track:   2 lba:     16462 (    65848) 03:41:37 adr: 1 control: 0 mode: -1
+ * ...
+ * track:  12 lba:    212405 (   849620) 47:14:05 adr: 1 control: 0 mode: -1
+ * track:  13 lba:    250948 (  1003792) 55:47:73 adr: 1 control: 4 mode: -1
+ * track:lout lba:    266286 (  1065144) 59:12:36 adr: 1 control: 4 mode: -1
+*/
+static int TOC_GetAudioRange(vcddev_toc_t *p_toc,
+                             int *pi_first, int *pi_last)
+{
+    if( p_toc->i_tracks < 1 )
+        return 0;
+
+    int i_first = p_toc->i_first_track;
+    int i_last = p_toc->i_last_track;
+    for(int i=i_first; i<p_toc->i_tracks; i++)
+    {
+        if((p_toc->p_sectors[i - 1].i_control & CD_ROM_DATA_FLAG) == 0)
+            break;
+        i_first++;
+    }
+    for(int i=i_last; i > 0; i--)
+    {
+        if((p_toc->p_sectors[i - 1].i_control & CD_ROM_DATA_FLAG) == 0)
+            break;
+        i_last--;
+    }
+
+    /* FIX copy protection TOC
+     * https://github.com/metabrainz/libdiscid/blob/e46249415eb6d657ecc63667b03d670a4347712f/src/toc.c#L101 */
+    do
+    {
+        vcddev_sector_t *p_last = &p_toc->p_sectors[i_last - p_toc->i_first_track];
+        vcddev_sector_t *p_lout = &p_toc->p_sectors[p_toc->i_tracks];
+        if(p_lout->i_lba > p_last->i_lba || i_last <= i_first)
+            break;
+        /* last audio is invalid, bigger than lead out */
+        i_last = i_last - 1;
+        p_toc->i_last_track = i_last;
+        p_last->i_lba -= CD_ROM_XA_INTERVAL;
+        p_toc->i_tracks--; /* change lead out */
+    } while( i_last > i_first );
+
+    *pi_first = i_first;
+    *pi_last = i_last;
+    return (i_last >= i_first) ? i_last - i_first + 1 : 0;
+}
+
 static int DemuxOpen(vlc_object_t *obj, vcddev_t *dev, unsigned track)
 {
     demux_t *demux = (demux_t *)obj;
@@ -233,15 +294,25 @@ static int DemuxOpen(vlc_object_t *obj, vcddev_t *dev, unsigned track)
         vcddev_toc_t *p_toc = ioctl_GetTOC(obj, dev, true);
         if(p_toc == NULL)
             goto error;
-        if (track > (unsigned)p_toc->i_tracks)
+
+        int i_cdda_tracks, i_cdda_first, i_cdda_last;
+        i_cdda_tracks = TOC_GetAudioRange(p_toc, &i_cdda_first, &i_cdda_last);
+
+        if (track == 0 || track > (unsigned) i_cdda_tracks)
         {
-            msg_Err(obj, "invalid track number: %u/%i", track, p_toc->i_tracks);
+            msg_Err(obj, "invalid track number: %u/%i", track, i_cdda_tracks);
             vcddev_toc_Free(p_toc);
             goto error;
         }
 
-        sys->start = p_toc->p_sectors[track - 1].i_lba;
-        sys->length = p_toc->p_sectors[track].i_lba - sys->start;
+        track--;
+        int i_first_sector = p_toc->p_sectors[track].i_lba;
+        int i_last_sector = p_toc->p_sectors[track + 1].i_lba;
+        if(i_cdda_first + track == (unsigned) i_cdda_last && p_toc->i_last_track > i_cdda_last)
+            i_last_sector -= CD_ROM_XA_INTERVAL;
+
+        sys->start = i_first_sector;
+        sys->length = i_last_sector - i_first_sector;
         vcddev_toc_Free(p_toc);
     }
 
@@ -272,6 +343,9 @@ typedef struct
 {
     vcddev_t    *vcddev;                            /* vcd device descriptor */
     vcddev_toc_t *p_toc;                            /* Tracks TOC */
+    int          i_cdda_tracks;                     /* # of audio tracks in TOC */
+    int          i_cdda_first;                      /* First .. */
+    int          i_cdda_last;                       /* Last .. */
     int          cdtextc;
     vlc_meta_t **cdtextv;
 #ifdef HAVE_LIBCDDB
@@ -455,19 +529,30 @@ static int ReadDir(stream_t *access, input_item_node_t *node)
     const vcddev_toc_t *p_toc = sys->p_toc;
 
     /* Build title table */
-    for (int i = 0; i < p_toc->i_tracks; i++)
+    const int i_start_track_offset = sys->i_cdda_first - sys->p_toc->i_first_track;
+    for (int i = 0; i < sys->i_cdda_tracks; i++)
     {
+        if(i < i_start_track_offset)
+            continue;
+
         msg_Dbg(access, "track[%d] start=%d", i, p_toc->p_sectors[i].i_lba);
 
         /* Initial/default name */
         char *name;
 
-        if (unlikely(asprintf(&name, _("Audio CD - Track %02i"), i + 1) == -1))
+        if (unlikely(asprintf(&name, _("Audio CD - Track %02i"),
+                              i - i_start_track_offset + 1 ) == -1))
             name = NULL;
 
         /* Create playlist items */
+        int i_first_sector = p_toc->p_sectors[i].i_lba;
+        int i_last_sector = p_toc->p_sectors[i + 1].i_lba;
+        if(sys->i_cdda_first + i == sys->i_cdda_last &&
+           p_toc->i_last_track > sys->i_cdda_last)
+            i_last_sector -= CD_ROM_XA_INTERVAL;
+
         const vlc_tick_t duration =
-            (vlc_tick_t)(p_toc->p_sectors[i + 1].i_lba - p_toc->p_sectors[i].i_lba)
+            (vlc_tick_t)(i_last_sector - i_first_sector)
             * CDDA_DATA_SIZE * CLOCK_FREQ / 44100 / 2 / 2;
 
         input_item_t *item = input_item_NewDisc(access->psz_url,
@@ -492,8 +577,7 @@ static int ReadDir(stream_t *access, input_item_node_t *node)
             free(opt);
         }
 
-        if (likely(asprintf(&opt, "cdda-last-sector=%i",
-                            p_toc->p_sectors[i + 1].i_lba) != -1))
+        if (likely(asprintf(&opt, "cdda-last-sector=%i", i_last_sector) != -1))
         {
             input_item_AddOption(item, opt, VLC_INPUT_OPTION_TRUSTED);
             free(opt);
@@ -607,7 +691,8 @@ static int AccessOpen(vlc_object_t *obj, vcddev_t *dev)
         goto error;
     }
 
-    if (sys->p_toc->i_tracks == 0)
+    sys->i_cdda_tracks = TOC_GetAudioRange(sys->p_toc, &sys->i_cdda_first, &sys->i_cdda_last);
+    if (sys->i_cdda_tracks == 0)
     {
         msg_Err(obj, "no audio tracks found");
         vcddev_toc_Free(sys->p_toc);
diff --git a/modules/access/vcd/cdrom.h b/modules/access/vcd/cdrom.h
index fe4dc34f4d..d8ee973605 100644
--- a/modules/access/vcd/cdrom.h
+++ b/modules/access/vcd/cdrom.h
@@ -37,6 +37,9 @@ enum {
 #define CD_ROM_XA_MODE2_F1_DATA_SIZE 2048
 #define CD_ROM_XA_MODE2_F2_DATA_SIZE 2324
 
+/* Subcode control flag */
+#define CD_ROM_DATA_FLAG    0x04
+
 /* size of a CD sector */
 #define CD_SECTOR_SIZE      CD_ROM_MODE1_DATA_SIZE
 



More information about the vlc-commits mailing list