stream_cdda: fix operation

The cdio API always reads in sectors (fixed CDIO_CD_FRAMESIZE_RAW
blocks). In the past, mpv/MPlayer streams had a way for a stream to
signal a sector size, so the stream's fill_buffer implementation could
ignore the length argument. Later, that was removed, but stream_cdda.c
was left with assuming that the read size was always larger than the
sector size (rightfully at the time). Even later, this assumption was
broken with commit f37f4de, when it was suddenly possibly that smaller
reads were performed (at ring buffer boundaries). It returned EOF if the
buffer size was too small, so playback stopped very early.

Fix this by explicitly handling arbitrary sizes.

Tested with a .cue/.bin file only.

Fixes: #7384
This commit is contained in:
wm4 2020-02-02 02:15:51 +01:00
parent 77a74d9eb5
commit f304a79935
1 changed files with 15 additions and 12 deletions

View File

@ -57,6 +57,8 @@ typedef struct cdda_params {
int sector;
int start_sector;
int end_sector;
uint8_t *data;
size_t data_pos;
// options
int speed;
@ -156,22 +158,23 @@ static void cdparanoia_callback(long int inpos, paranoia_cb_mode_t function)
static int fill_buffer(stream_t *s, void *buffer, int max_len)
{
cdda_priv *p = (cdda_priv *)s->priv;
int16_t *buf;
int i;
if (max_len < CDIO_CD_FRAMESIZE_RAW)
return -1;
if (!p->data || p->data_pos >= CDIO_CD_FRAMESIZE_RAW) {
if ((p->sector < p->start_sector) || (p->sector > p->end_sector))
return 0;
if ((p->sector < p->start_sector) || (p->sector > p->end_sector)) {
return 0;
p->data_pos = 0;
p->data = (uint8_t *)paranoia_read(p->cdp, cdparanoia_callback);
if (!p->data)
return 0;
p->sector++;
}
buf = paranoia_read(p->cdp, cdparanoia_callback);
if (!buf)
return 0;
p->sector++;
memcpy(buffer, buf, CDIO_CD_FRAMESIZE_RAW);
size_t copy = MPMIN(CDIO_CD_FRAMESIZE_RAW - p->data_pos, max_len);
memcpy(buffer, p->data + p->data_pos, copy);
p->data_pos += copy;
for (i = 0; i < p->cd->tracks; i++) {
if (p->cd->disc_toc[i].dwStartSector == p->sector - 1) {
@ -180,7 +183,7 @@ static int fill_buffer(stream_t *s, void *buffer, int max_len)
}
}
return CDIO_CD_FRAMESIZE_RAW;
return copy;
}
static int seek(stream_t *s, int64_t newpos)