diff options
| author | Brandon Low <lostlogic@rockbox.org> | 2006-03-24 13:43:15 +0000 |
|---|---|---|
| committer | Brandon Low <lostlogic@rockbox.org> | 2006-03-24 13:43:15 +0000 |
| commit | 86f1e2ead283d86f6896ca0f98c0b711da5e2cfe (patch) | |
| tree | fe961ef2fdfe8a5d6317604246acf63440326435 | |
| parent | b1cd32913dcd9bba7960c1f8f3b384ee1ff5a259 (diff) | |
| download | rockbox-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.c | 2 | ||||
| -rw-r--r-- | apps/codecs.h | 18 | ||||
| -rw-r--r-- | apps/codecs/flac.c | 8 | ||||
| -rw-r--r-- | apps/pcmbuf.c | 15 | ||||
| -rw-r--r-- | apps/playback.c | 184 | ||||
| -rw-r--r-- | apps/playback.h | 22 |
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 */ |