summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-02-02 02:15:51 +0100
committerwm4 <wm4@nowhere>2020-02-02 02:15:51 +0100
commitf304a799350ced0f0a8882843e17bcd5fcea2e25 (patch)
tree779be92d5eb9ca44365bf9df4447bcb05eef58a4 /stream
parent77a74d9eb55513893f3a3a23c4d808c1890b2811 (diff)
downloadmpv-f304a799350ced0f0a8882843e17bcd5fcea2e25.tar.bz2
mpv-f304a799350ced0f0a8882843e17bcd5fcea2e25.tar.xz
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
Diffstat (limited to 'stream')
-rw-r--r--stream/stream_cdda.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/stream/stream_cdda.c b/stream/stream_cdda.c
index 87be426992..090c439987 100644
--- a/stream/stream_cdda.c
+++ b/stream/stream_cdda.c
@@ -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;
- buf = paranoia_read(p->cdp, cdparanoia_callback);
- if (!buf)
- return 0;
+ p->sector++;
+ }
- 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)