[vlc-commits] access: cdda: fix audio/data mixed mode
Francois Cartegnie
git at videolan.org
Sat Jun 1 00:27:51 CEST 2019
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri May 31 18:04:40 2019 +0200| [182133eab2c6cf3c9ae98dd6383a774d07b5762d] | 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=182133eab2c6cf3c9ae98dd6383a774d07b5762d
---
NEWS | 1 +
modules/access/cdda.c | 105 ++++++++++++++++++++++++++++++++++++++++-----
modules/access/vcd/cdrom.h | 6 +++
3 files changed, 102 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..f0379fa439 100644
--- a/modules/access/vcd/cdrom.h
+++ b/modules/access/vcd/cdrom.h
@@ -37,6 +37,12 @@ enum {
#define CD_ROM_XA_MODE2_F1_DATA_SIZE 2048
#define CD_ROM_XA_MODE2_F2_DATA_SIZE 2324
+#define CD_ROM_XA_FRAMES 75
+#define CD_ROM_XA_INTERVAL ((60 + 90 + 2) * CD_ROM_XA_FRAMES)
+
+/* 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