diff --git a/apps/buffering.c b/apps/buffering.c index 800686541a..83ff0d5a31 100644 --- a/apps/buffering.c +++ b/apps/buffering.c @@ -398,8 +398,8 @@ static struct memory_handle *find_handle(const unsigned int handle_id) a memory_handle after correcting for wraps or if the handle is not found in the linked list for adjustment. This function has no side effects if NULL is returned. */ -static bool move_handle(struct memory_handle **h, - size_t *delta, const size_t data_size) +static bool move_handle(struct memory_handle **h, size_t *delta, + const size_t data_size, bool can_wrap) { struct memory_handle *dest; const struct memory_handle *src; @@ -427,13 +427,13 @@ static bool move_handle(struct memory_handle **h, if (overlap > 0) { /* Some part of the struct + data would wrap, maybe ok */ - size_t correction; + size_t correction = 0; /* If the overlap lands inside the memory_handle */ if ((unsigned)overlap > data_size) { /* Correct the position and real delta to prevent the struct from * wrapping, this guarantees an aligned delta, I think */ correction = overlap - data_size; - } else { + } else if (!can_wrap) { /* Otherwise the overlap falls in the data area and must all be * backed out. This may become conditional if ever we move * data that is allowed to wrap (ie audio) */ @@ -441,15 +441,17 @@ static bool move_handle(struct memory_handle **h, /* Align correction to four bytes, up */ correction = (correction+3) & ~3; } - if (final_delta < correction + sizeof(struct memory_handle)) { - /* Delta cannot end up less than the size of the struct */ - mutex_unlock(&llist_mutex); - return false; - } + if (correction) { + if (final_delta < correction + sizeof(struct memory_handle)) { + /* Delta cannot end up less than the size of the struct */ + mutex_unlock(&llist_mutex); + return false; + } - newpos -= correction; - overlap -= correction; /* Used below to know how to split the data */ - final_delta -= correction; + newpos -= correction; + overlap -= correction;/* Used below to know how to split the data */ + final_delta -= correction; + } } dest = (struct memory_handle *)(&buffer[newpos]); @@ -530,6 +532,7 @@ static bool yield_codec(void) while (pcmbuf_is_lowdata() && !filebuf_is_lowdata()) { sleep(2); + trigger_cpu_boost(); if (!queue_empty(&buffering_queue)) return true; @@ -540,7 +543,7 @@ static bool yield_codec(void) /* Buffer data for the given handle. Return the amount of data buffered or -1 if the handle wasn't found */ -static ssize_t buffer_handle(int handle_id, bool force) +static ssize_t buffer_handle(int handle_id) { logf("buffer_handle(%d)", handle_id); struct memory_handle *h = find_handle(handle_id); @@ -568,6 +571,7 @@ static ssize_t buffer_handle(int handle_id, bool force) trigger_cpu_boost(); + bool breakable = h->type==TYPE_PACKET_AUDIO; ssize_t ret = 0; while (h->filerem > 0) { @@ -611,11 +615,7 @@ static ssize_t buffer_handle(int handle_id, bool force) h->filerem -= rc; /* Stop buffering if new queue events have arrived */ - /* FIXME: This may sleep, if it does it will untrigger the - * cpu boost for this thread. If the codec's low data - * situation was very short lived that could leave us filling - * w/o boost */ - if (!force && yield_codec()) + if (breakable && yield_codec()) break; } @@ -692,8 +692,10 @@ static void shrink_handle(int handle_id) if (!h) return; - if (h->next && (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET || - h->type == TYPE_IMAGE) && h->filerem == 0 ) + if (h->next && h->filerem == 0 && + (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET || + h->type == TYPE_IMAGE || h->type == TYPE_CODEC || + h->type == TYPE_ATOMIC_AUDIO)) { /* metadata handle: we can move all of it */ size_t handle_distance = @@ -701,7 +703,7 @@ static void shrink_handle(int handle_id) delta = handle_distance - h->available; /* The value of delta might change for alignment reasons */ - if (!move_handle(&h, &delta, h->available)) + if (!move_handle(&h, &delta, h->available, h->type==TYPE_CODEC)) return; size_t olddata = h->data; @@ -720,7 +722,7 @@ static void shrink_handle(int handle_id) { /* only move the handle struct */ delta = RINGBUF_SUB(h->ridx, h->data); - if (!move_handle(&h, &delta, 0)) + if (!move_handle(&h, &delta, 0, true)) return; h->data = RINGBUF_ADD(h->data, delta); @@ -737,7 +739,7 @@ static void fill_buffer(void) struct memory_handle *m = first_handle; while (queue_empty(&buffering_queue) && m) { if (m->filerem > 0) { - buffer_handle(m->id, false); + buffer_handle(m->id); } m = m->next; } @@ -805,8 +807,9 @@ int bufopen(const char *file, size_t offset, enum data_type type) return ERR_FILE_ERROR; size_t size = filesize(fd); + bool can_wrap = type==TYPE_PACKET_AUDIO || type==TYPE_CODEC; - struct memory_handle *h = add_handle(size-offset, type==TYPE_AUDIO, false); + struct memory_handle *h = add_handle(size-offset, can_wrap, false); if (!h) { DEBUGF("bufopen: failed to add handle\n"); @@ -1137,7 +1140,8 @@ static void shrink_buffer(bool audio, bool other) { /* shrink selected buffers */ struct memory_handle *m = first_handle; while (m) { - if ((m->type==TYPE_AUDIO && audio) || (m->type!=TYPE_AUDIO && other)) + if ((m->type==TYPE_PACKET_AUDIO && audio) || + (m->type!=TYPE_PACKET_AUDIO && other)) shrink_handle(m->id); m = m->next; } @@ -1156,7 +1160,7 @@ void buffering_thread(void) case Q_BUFFER_HANDLE: LOGFQUEUE("buffering < Q_BUFFER_HANDLE"); queue_reply(&buffering_queue, 1); - buffer_handle((int)ev.data, true); + buffer_handle((int)ev.data); break; case Q_RESET_HANDLE: diff --git a/apps/buffering.h b/apps/buffering.h index f7e298f72c..46f2fadf47 100644 --- a/apps/buffering.h +++ b/apps/buffering.h @@ -26,8 +26,8 @@ enum data_type { TYPE_CODEC, - TYPE_AUDIO, - TYPE_STREAM, + TYPE_PACKET_AUDIO, + TYPE_ATOMIC_AUDIO, TYPE_ID3, TYPE_CUESHEET, TYPE_IMAGE, diff --git a/apps/codecs.c b/apps/codecs.c index e41e047720..eaf81d3e22 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -38,6 +38,7 @@ #include "keyboard.h" #include "mpeg.h" #include "buffer.h" +#include "buffering.h" #include "mp3_playback.h" #include "playback.h" #include "backlight.h" @@ -57,8 +58,7 @@ #if CONFIG_CODEC == SWCODEC unsigned char codecbuf[CODEC_SIZE]; #endif -void *sim_codec_load_ram(char* codecptr, int size, - void* ptr2, int bufwrap, void **pd); +void *sim_codec_load_ram(char* codecptr, int size, void **pd); void sim_codec_close(void *pd); #else #define sim_codec_close(x) @@ -171,23 +171,11 @@ void codec_get_full_path(char *path, const char *codec_root_fn) codec_root_fn); } -int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, - struct codec_api *api) +static int codec_load_ram(int size, struct codec_api *api) { struct codec_header *hdr; int status; #ifndef SIMULATOR - int copy_n; - - if ((char *)&codecbuf[0] != codecptr) { - size = MIN(size, CODEC_SIZE); - copy_n = MIN(size, bufwrap); - memcpy(codecbuf, codecptr, copy_n); - if (size - copy_n > 0) { - memcpy(&codecbuf[copy_n], ptr2, size - copy_n); - } - api->discard_codec(); - } hdr = (struct codec_header *)codecbuf; if (size <= (signed)sizeof(struct codec_header) @@ -206,14 +194,16 @@ int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, #else /* SIMULATOR */ void *pd; - hdr = sim_codec_load_ram(codecptr, size, ptr2, bufwrap, &pd); - api->discard_codec(); + hdr = sim_codec_load_ram(codecbuf, size, &pd); if (pd == NULL) return CODEC_ERROR; if (hdr == NULL || hdr->magic != CODEC_MAGIC +#ifdef HAVE_RECORDING + && hdr->magic != CODEC_ENC_MAGIC +#endif || hdr->target_id != TARGET_ID) { sim_codec_close(pd); return CODEC_ERROR; @@ -233,6 +223,32 @@ int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, return status; } +int codec_load_buf(unsigned int hid, int size, struct codec_api *api) { + int rc; + rc = bufread(hid, size, codecbuf); + if (rc < 0) { + if (rc == ERR_DATA_NOT_READY) { + buf_request_buffer_handle(hid); + } else { + logf("error loading codec"); + return CODEC_ERROR; + } + do { + rc = bufread(hid, size, codecbuf); + } while (rc == ERR_DATA_NOT_READY); + } + if (rc < 0) { + logf("error loading codec"); + return CODEC_ERROR; + } + if (rc < size) { + logf("codec ended %d early",size - rc); + return CODEC_ERROR; + } + api->discard_codec(); + return codec_load_ram(size, api); +} + int codec_load_file(const char *plugin, struct codec_api *api) { char msgbuf[80]; @@ -257,5 +273,5 @@ int codec_load_file(const char *plugin, struct codec_api *api) return CODEC_ERROR; } - return codec_load_ram(codecbuf, (size_t)rc, NULL, 0, api); + return codec_load_ram((size_t)rc, api); } diff --git a/apps/codecs.h b/apps/codecs.h index a59a791d42..638c43ba22 100644 --- a/apps/codecs.h +++ b/apps/codecs.h @@ -284,8 +284,7 @@ extern unsigned char plugin_end_addr[]; void codec_get_full_path(char *path, const char *codec_root_fn); /* defined by the codec loader (codec.c) */ -int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, - struct codec_api *api); +int codec_load_buf(unsigned int hid, int size, struct codec_api *api); int codec_load_file(const char* codec, struct codec_api *api); /* defined by the codec */ diff --git a/apps/playback.c b/apps/playback.c index 5cd8e6def3..d9f7fa97c2 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -361,26 +361,6 @@ static struct mp3entry *bufgetid3(int handle_id) return id3; } -static void *bufgetcodec(struct track_info *track) -{ - void *ptr; - ssize_t ret = bufgetdata(track->codec_hid, track->codecsize, &ptr); - - if (ret == ERR_DATA_NOT_READY) { - buf_request_buffer_handle(track->codec_hid); - } - - while (ret == ERR_DATA_NOT_READY) { - sleep(1); - ret = bufgetdata(track->codec_hid, track->codecsize, &ptr); - } - - if (ret < 0) - return NULL; - else - return ptr; -} - static bool clear_track_info(struct track_info *track) { if (!track) @@ -1876,8 +1856,6 @@ static void codec_thread(void) { struct queue_event ev; int status; - size_t wrap; - void *codecptr; while (1) { status = 0; @@ -1933,10 +1911,8 @@ static void codec_thread(void) #endif set_current_codec(CODEC_IDX_AUDIO); ci.stop_codec = false; - codecptr = bufgetcodec(CUR_TI); - wrap = (size_t)&filebuf[filebuflen] - (size_t)codecptr; - status = codec_load_ram(codecptr, CUR_TI->codecsize, - &filebuf[0], wrap, &ci); + status = + codec_load_buf(CUR_TI->codec_hid, CUR_TI->codecsize, &ci); #ifdef PLAYBACK_VOICE semaphore_release(&sem_codecthread); #endif @@ -2447,6 +2423,7 @@ static bool audio_load_track(int offset, bool start_play) } struct mp3entry *track_id3; + enum data_type type = TYPE_PACKET_AUDIO; if (track_widx == track_ridx) track_id3 = &curtrack_id3; @@ -2487,12 +2464,16 @@ static bool audio_load_track(int offset, bool start_play) case AFMT_APE: track_id3->offset = offset; break; + case AFMT_NSF: + case AFMT_SPC: + type = TYPE_ATOMIC_AUDIO; + break; } } logf("alt:%s", trackname); - tracks[track_widx].audio_hid = bufopen(trackname, file_offset, TYPE_AUDIO); + tracks[track_widx].audio_hid = bufopen(trackname, file_offset, type); if (tracks[track_widx].audio_hid <= 0) return false;