summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Low <lostlogic@rockbox.org>2006-03-24 13:43:15 +0000
committerBrandon Low <lostlogic@rockbox.org>2006-03-24 13:43:15 +0000
commit86f1e2ead283d86f6896ca0f98c0b711da5e2cfe (patch)
treefe961ef2fdfe8a5d6317604246acf63440326435
parentb1cd32913dcd9bba7960c1f8f3b384ee1ff5a259 (diff)
downloadrockbox-86f1e2ead283d86f6896ca0f98c0b711da5e2cfe.zip
rockbox-86f1e2ead283d86f6896ca0f98c0b711da5e2cfe.tar.gz
rockbox-86f1e2ead283d86f6896ca0f98c0b711da5e2cfe.tar.bz2
rockbox-86f1e2ead283d86f6896ca0f98c0b711da5e2cfe.tar.xz
Convert playback.c to use unsigned byte counters, and _minor_ refactoring of buffer callbacks
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9227 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs.c2
-rw-r--r--apps/codecs.h18
-rw-r--r--apps/codecs/flac.c8
-rw-r--r--apps/pcmbuf.c15
-rw-r--r--apps/playback.c184
-rw-r--r--apps/playback.h22
6 files changed, 125 insertions, 124 deletions
diff --git a/apps/codecs.c b/apps/codecs.c
index 804dd2e..298e5e1 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -143,6 +143,7 @@ struct codec_api ci = {
strncasecmp,
memset,
memcpy,
+ memmove,
_ctype_,
atoi,
strchr,
@@ -215,7 +216,6 @@ struct codec_api ci = {
/* new stuff at the end, sort into place next time
the API gets incompatible */
- memmove,
};
int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
diff --git a/apps/codecs.h b/apps/codecs.h
index 7a0fab2..d28afc7 100644
--- a/apps/codecs.h
+++ b/apps/codecs.h
@@ -85,12 +85,12 @@
#define CODEC_MAGIC 0x52434F44 /* RCOD */
/* increase this every time the api struct changes */
-#define CODEC_API_VERSION 4
+#define CODEC_API_VERSION 5
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
-#define CODEC_MIN_API_VERSION 3
+#define CODEC_MIN_API_VERSION 5
/* codec return codes */
enum codec_status {
@@ -125,7 +125,7 @@ struct codec_api {
long seek_time;
/* Returns buffer to malloc array. Only codeclib should need this. */
- void* (*get_codec_memory)(long *size);
+ void* (*get_codec_memory)(size_t *size);
/* Insert PCM data into audio buffer for playback. Playback will start
automatically. */
bool (*pcmbuf_insert)(const char *data, size_t length);
@@ -135,18 +135,18 @@ struct codec_api {
/* Read next <size> amount bytes from file buffer to <ptr>.
Will return number of bytes read or 0 if end of file. */
- long (*read_filebuf)(void *ptr, long size);
+ size_t (*read_filebuf)(void *ptr, size_t size);
/* Request pointer to file buffer which can be used to read
<realsize> amount of data. <reqsize> tells the buffer system
how much data it should try to allocate. If <realsize> is 0,
end of file is reached. */
- void* (*request_buffer)(long *realsize, long reqsize);
+ void* (*request_buffer)(size_t *realsize, size_t reqsize);
/* Advance file buffer position by <amount> amount of bytes. */
- void (*advance_buffer)(long amount);
+ void (*advance_buffer)(size_t amount);
/* Advance file buffer to a pointer location inside file buffer. */
void (*advance_buffer_loc)(void *ptr);
/* Seek file buffer to position <newpos> beginning of file. */
- bool (*seek_buffer)(off_t newpos);
+ bool (*seek_buffer)(size_t newpos);
/* Codec should call this function when it has done the seeking. */
void (*seek_complete)(void);
/* Calculate mp3 seek position from given time data in ms. */
@@ -156,7 +156,7 @@ struct codec_api {
codec should exit immediately with PLUGIN_OK status. */
bool (*request_next_track)(void);
- void (*set_offset)(unsigned int value);
+ void (*set_offset)(size_t value);
/* Configure different codec buffer parameters. */
void (*configure)(int setting, void *value);
@@ -214,6 +214,7 @@ struct codec_api {
int (*strncasecmp)(const char *s1, const char *s2, size_t n);
void* (*memset)(void *dst, int c, size_t length);
void* (*memcpy)(void *out, const void *in, size_t n);
+ void* (*memmove)(void *out, const void *in, size_t n);
const char *_ctype_;
int (*atoi)(const char *str);
char *(*strchr)(const char *s, int c);
@@ -292,7 +293,6 @@ struct codec_api {
/* new stuff at the end, sort into place next time
the API gets incompatible */
- void* (*memmove)(void *out, const void *in, size_t n);
};
/* codec header */
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c
index fa263c1..f95ae2a 100644
--- a/apps/codecs/flac.c
+++ b/apps/codecs/flac.c
@@ -118,11 +118,9 @@ static bool flac_init(FLACContext* fc, int first_frame_offset)
if ((buf[0] & 0x7f) == 0) /* 0 is the STREAMINFO block */
{
- /* FIXME: Don't trust the value of blocklength */
- if (ci->read_filebuf(buf, blocklength) < 0)
- {
- return false;
- }
+ /* FIXME: Don't trust the value of blocklength, use actual return
+ * value in bytes instead */
+ ci->read_filebuf(buf, blocklength);
fc->filesize = ci->filesize;
fc->min_blocksize = (buf[0] << 8) | buf[1];
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index 6a8e2f2..2d61f23 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -401,8 +401,6 @@ void pcmbuf_pause(bool pause) {
/* Force playback. */
void pcmbuf_play_start(void)
{
- mutex_lock(&pcmbuf_mutex);
-
if (!pcm_is_playing() && pcmbuf_unplayed_bytes)
{
/** Prevent a very tiny pop from happening by muting audio
@@ -417,8 +415,6 @@ void pcmbuf_play_start(void)
/* Now unmute the audio. */
pcm_mute(false);
}
-
- mutex_unlock(&pcmbuf_mutex);
}
/**
@@ -426,27 +422,22 @@ void pcmbuf_play_start(void)
*/
static void pcmbuf_flush_fillpos(void)
{
- mutex_lock(&pcmbuf_mutex);
-
if (audiobuffer_fillpos) {
/* Never use the last buffer descriptor */
while (pcmbuf_write == pcmbuf_write_end) {
logf("pcmbuf_flush_fillpos no descriptors");
/* Deboost to let the playback catchup */
pcmbuf_boost(false);
- /* Let someone else have fun in the meantime */
- sleep(1);
- /* This is a fatal error situation that should never happen. */
+ /* If this happens, something is being stupid */
if (!pcm_is_playing()) {
logf("pcmbuf_flush_fillpos error");
pcmbuf_play_start();
- return ;
}
+ /* Let approximately one chunk of data playback */
+ sleep(PCMBUF_TARGET_CHUNK/(NATIVE_FREQUENCY * 4) / 5);
}
pcmbuf_add_chunk();
}
-
- mutex_unlock(&pcmbuf_mutex);
}
/**
diff --git a/apps/playback.c b/apps/playback.c
index 0c04057..bf6e5bc 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -145,7 +145,7 @@ static struct mutex mutex_codecthread;
static struct mp3entry id3_voice;
static char *voicebuf;
-static int voice_remaining;
+static size_t voice_remaining;
static bool voice_is_playing;
static void (*voice_getmore)(unsigned char** start, int* size);
@@ -159,14 +159,14 @@ extern unsigned char codecbuf[];
static char *filebuf;
/* Total size of the ring buffer. */
-int filebuflen;
+size_t filebuflen;
/* Bytes available in the buffer. */
-int filebufused;
+size_t filebufused;
/* Ring buffer read and write indexes. */
-static volatile int buf_ridx;
-static volatile int buf_widx;
+static volatile size_t buf_ridx;
+static volatile size_t buf_widx;
#ifndef SIMULATOR
static unsigned char *iram_buf[2];
@@ -187,7 +187,7 @@ static bool track_changed;
static int current_fd;
/* Information about how many bytes left on the buffer re-fill run. */
-static long fill_bytesleft;
+static size_t fill_bytesleft;
/* Track info structure about songs in the file buffer. */
static struct track_info tracks[MAX_TRACK];
@@ -215,10 +215,10 @@ void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track);
static void playback_init(void);
/* Configuration */
-static int conf_bufferlimit;
-static int conf_watermark;
-static int conf_filechunk;
-static int buffer_margin;
+static size_t conf_bufferlimit;
+static size_t conf_watermark;
+static size_t conf_filechunk;
+static size_t buffer_margin;
static bool v1first = false;
@@ -388,7 +388,7 @@ bool codec_pcmbuf_insert_callback(const char *buf, size_t length)
length);
}
-void* get_codec_memory_callback(long *size)
+void* get_codec_memory_callback(size_t *size)
{
*size = MALLOC_BUFSIZE;
if (voice_codec_loaded)
@@ -413,7 +413,8 @@ void codec_set_elapsed_callback(unsigned int value)
{
unsigned int latency;
- if (ci.stop_codec || current_codec == CODEC_IDX_VOICE)
+ /* We don't save or display offsets for voice */
+ if (current_codec == CODEC_IDX_VOICE)
return ;
#ifdef AB_REPEAT_ENABLE
@@ -429,11 +430,12 @@ void codec_set_elapsed_callback(unsigned int value)
}
}
-void codec_set_offset_callback(unsigned int value)
+void codec_set_offset_callback(size_t value)
{
unsigned int latency;
- if (ci.stop_codec || current_codec == CODEC_IDX_VOICE)
+ /* We don't save or display offsets for voice */
+ if (current_codec == CODEC_IDX_VOICE)
return ;
latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8;
@@ -445,43 +447,56 @@ void codec_set_offset_callback(unsigned int value)
}
}
-long codec_filebuf_callback(void *ptr, long size)
+static void advance_buffer_counters(size_t amount) {
+ buf_ridx += amount;
+ if (buf_ridx >= filebuflen)
+ buf_ridx -= filebuflen;
+ ci.curpos += amount;
+ cur_ti->available -= amount;
+ filebufused -= amount;
+}
+
+/* copy up-to size bytes into ptr and return the actual size copied */
+size_t codec_filebuf_callback(void *ptr, size_t size)
{
char *buf = (char *)ptr;
- int copy_n;
- int part_n;
+ size_t copy_n;
+ size_t part_n;
if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE)
return 0;
- copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem);
+ /* The ammount to copy is the lesser of the requested amount and the
+ * amount left of the current track (both on disk and already loaded) */
+ copy_n = MIN(size, cur_ti->available + cur_ti->filerem);
+ /* Nothing requested OR nothing left */
+ if (copy_n == 0)
+ return 0;
+
+ /* Let the disk buffer catch fill until enough data is available */
while (copy_n > cur_ti->available) {
yield();
if (ci.stop_codec || ci.reload_codec)
return 0;
}
- if (copy_n == 0)
- return 0;
-
+ /* Copy as much as possible without wrapping */
part_n = MIN(copy_n, filebuflen - buf_ridx);
memcpy(buf, &filebuf[buf_ridx], part_n);
+ /* Copy the rest in the case of a wrap */
if (part_n < copy_n) {
memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
}
- buf_ridx += copy_n;
- if (buf_ridx >= filebuflen)
- buf_ridx -= filebuflen;
- ci.curpos += copy_n;
- cur_ti->available -= copy_n;
- filebufused -= copy_n;
+ /* Update read and other position pointers */
+ advance_buffer_counters(copy_n);
+ /* Return the actual amount of data copied to the buffer */
return copy_n;
}
-void* voice_request_data(long *realsize, long reqsize)
+void* voice_request_data(size_t *realsize, size_t reqsize)
{
while (queue_empty(&voice_codec_queue) && (voice_remaining == 0
|| voicebuf == NULL) && !ci_voice.stop_codec)
@@ -503,10 +518,8 @@ void* voice_request_data(long *realsize, long reqsize)
if (voice_remaining)
{
voice_is_playing = true;
- break ;
}
-
- if (voice_getmore != NULL)
+ else if (voice_getmore != NULL)
{
voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
@@ -519,13 +532,8 @@ void* voice_request_data(long *realsize, long reqsize)
}
}
- if (reqsize < 0)
- reqsize = 0;
-
voice_is_playing = true;
- *realsize = voice_remaining;
- if (*realsize > reqsize)
- *realsize = reqsize;
+ *realsize = MIN(voice_remaining, reqsize);
if (*realsize == 0)
return NULL;
@@ -533,9 +541,9 @@ void* voice_request_data(long *realsize, long reqsize)
return voicebuf;
}
-void* codec_request_buffer_callback(long *realsize, long reqsize)
+void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
{
- long part_n;
+ size_t short_n, copy_n, buf_rem;
/* Voice codec. */
if (current_codec == CODEC_IDX_VOICE) {
@@ -547,12 +555,13 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
return NULL;
}
- *realsize = MIN((off_t)reqsize, (off_t)cur_ti->available + cur_ti->filerem);
- if (*realsize == 0) {
+ copy_n = MIN(reqsize, cur_ti->available + cur_ti->filerem);
+ if (copy_n == 0) {
+ *realsize = 0;
return NULL;
}
- while ((int)*realsize > cur_ti->available) {
+ while (copy_n > cur_ti->available) {
yield();
if (ci.stop_codec || ci.reload_codec) {
*realsize = 0;
@@ -560,19 +569,24 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
}
}
- part_n = MIN((int)*realsize, filebuflen - buf_ridx);
- if (part_n < *realsize) {
- part_n += GUARD_BUFSIZE;
- if (part_n < *realsize)
- *realsize = part_n;
- memcpy(&filebuf[filebuflen], &filebuf[0], *realsize -
- (filebuflen - buf_ridx));
+ /* How much is left at the end of the file buffer before wrap? */
+ buf_rem = filebuflen - buf_ridx;
+ /* If we can't satisfy the request without wrapping */
+ if (buf_rem < copy_n) {
+ /* How short are we? */
+ short_n = copy_n - buf_rem;
+ /* If we can fudge it with the guardbuf */
+ if (short_n < GUARD_BUFSIZE)
+ memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
+ else
+ copy_n = buf_rem;
}
+ *realsize = copy_n;
return (char *)&filebuf[buf_ridx];
}
-static bool rebuffer_and_seek(int newpos)
+static bool rebuffer_and_seek(size_t newpos)
{
int fd;
@@ -613,11 +627,11 @@ static bool rebuffer_and_seek(int newpos)
return true;
}
-void codec_advance_buffer_callback(long amount)
+void codec_advance_buffer_callback(size_t amount)
{
if (current_codec == CODEC_IDX_VOICE) {
//logf("voice ad.buf:%d", amount);
- amount = MAX(0, MIN(amount, voice_remaining));
+ amount = MIN(amount, voice_remaining);
voicebuf += amount;
voice_remaining -= amount;
@@ -636,23 +650,19 @@ void codec_advance_buffer_callback(long amount)
return ;
}
- buf_ridx += amount;
- if (buf_ridx >= filebuflen)
- buf_ridx -= filebuflen;
- cur_ti->available -= amount;
- filebufused -= amount;
- ci.curpos += amount;
+ advance_buffer_counters(amount);
+
codec_set_offset_callback(ci.curpos);
}
void codec_advance_buffer_loc_callback(void *ptr)
{
- long amount;
+ size_t amount;
if (current_codec == CODEC_IDX_VOICE)
- amount = (long)ptr - (long)voicebuf;
+ amount = (size_t)ptr - (size_t)voicebuf;
else
- amount = (long)ptr - (long)&filebuf[buf_ridx];
+ amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
codec_advance_buffer_callback(amount);
}
@@ -672,16 +682,13 @@ void codec_seek_complete_callback(void)
ci.seek_time = 0;
}
-bool codec_seek_buffer_callback(off_t newpos)
+bool codec_seek_buffer_callback(size_t newpos)
{
int difference;
if (current_codec == CODEC_IDX_VOICE)
return false;
- if (newpos < 0)
- newpos = 0;
-
if (newpos >= cur_ti->filesize)
newpos = cur_ti->filesize - 1;
@@ -706,9 +713,9 @@ bool codec_seek_buffer_callback(off_t newpos)
logf("seek: -%d", difference);
filebufused += difference;
cur_ti->available += difference;
+ if (buf_ridx < (unsigned)difference)
+ buf_ridx += filebuflen;
buf_ridx -= difference;
- if (buf_ridx < 0)
- buf_ridx = filebuflen + buf_ridx;
ci.curpos -= difference;
return true;
@@ -716,7 +723,7 @@ bool codec_seek_buffer_callback(off_t newpos)
static void set_filebuf_watermark(int seconds)
{
- long bytes;
+ size_t bytes;
if (current_codec == CODEC_IDX_VOICE)
return ;
@@ -724,7 +731,7 @@ static void set_filebuf_watermark(int seconds)
if (!filebuf)
return; /* Audio buffers not yet set up */
- bytes = MAX((int)cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark);
+ bytes = MAX(cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark);
bytes = MIN(bytes, filebuflen / 2);
conf_watermark = bytes;
}
@@ -803,14 +810,15 @@ void strip_id3v1_tag(void)
{
int i;
static const unsigned char tag[] = "TAG";
- int tagptr;
+ size_t tagptr;
bool found = true;
if (filebufused >= 128)
{
- tagptr = buf_widx - 128;
- if (tagptr < 0)
- tagptr += filebuflen;
+ if (buf_widx < 128)
+ tagptr = filebuflen + buf_widx - 128;
+ else
+ tagptr = buf_widx - 128;
for(i = 0;i < 3;i++)
{
@@ -839,7 +847,9 @@ void strip_id3v1_tag(void)
static void audio_fill_file_buffer(void)
{
- long i, size;
+ unsigned long i;
+ size_t size;
+ size_t copy_n;
int rc;
if (current_fd < 0)
@@ -858,9 +868,9 @@ static void audio_fill_file_buffer(void)
if (fill_bytesleft == 0)
break ;
- rc = MIN(conf_filechunk, filebuflen - buf_widx);
- rc = MIN(rc, fill_bytesleft);
- rc = read(current_fd, &filebuf[buf_widx], rc);
+ copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
+ copy_n = MIN(copy_n, fill_bytesleft);
+ rc = read(current_fd, &filebuf[buf_widx], copy_n);
if (rc <= 0) {
tracks[track_widx].filerem = 0;
break ;
@@ -901,11 +911,12 @@ static int get_codec_base_type(int type)
static bool loadcodec(bool start_play)
{
- off_t size;
+ size_t size;
int fd;
- int i, rc;
+ unsigned int i;
+ int rc;
const char *codec_path;
- int copy_n;
+ size_t copy_n;
int prev_track;
switch (tracks[track_widx].id3.codectype) {
@@ -994,7 +1005,7 @@ static bool loadcodec(bool start_play)
}
size = filesize(fd);
- if ((off_t)fill_bytesleft < size + conf_watermark) {
+ if (fill_bytesleft < size + conf_watermark) {
logf("Not enough space");
/* Set codectype back to zero to indicate no codec was loaded. */
tracks[track_widx].id3.codectype = 0;
@@ -1464,7 +1475,10 @@ static void audio_check_buffer(void)
/* Limit buffering size at first run. */
if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit
- filebufused) {
- fill_bytesleft = MAX(0, conf_bufferlimit - filebufused);
+ if (conf_bufferlimit > filebufused)
+ fill_bytesleft = conf_bufferlimit - filebufused;
+ else
+ fill_bytesleft = 0;
}
/* Try to load remainings of the file. */
@@ -1631,11 +1645,11 @@ static int skip_previous_track(bool inside_codec_thread)
cur_ti->available = cur_ti->filesize - cur_ti->filerem;
cur_ti = &tracks[track_ridx];
- buf_ridx -= cur_ti->filesize;
filebufused += cur_ti->filesize;
cur_ti->available = cur_ti->filesize;
- if (buf_ridx < 0)
+ if (buf_ridx < cur_ti->filesize)
buf_ridx += filebuflen;
+ buf_ridx -= cur_ti->filesize;
audio_update_trackinfo();
@@ -2096,8 +2110,6 @@ void voice_init(void)
{
logf("Terminating voice codec");
ci_voice.stop_codec = true;
- if (current_codec != CODEC_IDX_VOICE)
- swap_codec();
sleep(1);
}
diff --git a/apps/playback.h b/apps/playback.h
index 187ac00..2504652 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -35,18 +35,18 @@
#define MAX_TRACK 32
struct track_info {
- struct mp3entry id3; /* TAG metadata */
- char *codecbuf; /* Pointer to codec buffer */
- long codecsize; /* Codec length in bytes */
+ struct mp3entry id3; /* TAG metadata */
+ char *codecbuf; /* Pointer to codec buffer */
+ size_t codecsize; /* Codec length in bytes */
- off_t filerem; /* Remaining bytes of file NOT in buffer */
- off_t filesize; /* File total length */
- off_t filepos; /* Read position of file for next buffer fill */
- off_t start_pos; /* Position to first bytes of file in buffer */
- volatile int available; /* Available bytes to read from buffer */
- bool taginfo_ready; /* Is metadata read */
- int playlist_offset; /* File location in playlist */
- bool event_sent; /* Has event callback functions been called? */
+ size_t filerem; /* Remaining bytes of file NOT in buffer */
+ size_t filesize; /* File total length */
+ size_t filepos; /* Read position of file for next buffer fill */
+ size_t start_pos; /* Position to first bytes of file in buffer */
+ volatile size_t available; /* Available bytes to read from buffer */
+ bool taginfo_ready; /* Is metadata read */
+ int playlist_offset; /* File location in playlist */
+ bool event_sent; /* Has event callback functions been called? */
};
/* Functions */