Improve upon my hackity hack from before by separating audio into two types: that which may be large and can be streamed and that which is small and cannot be streamed. While modifying types, allow codecs to split across the buffer wrap and dig out/move around the code that reads a codec off of the buffer to facilitate that simple sounding change.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15408 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Brandon Low 2007-11-02 14:06:48 +00:00
parent 21f0552947
commit dcca586a9b
5 changed files with 75 additions and 75 deletions

View file

@ -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:

View file

@ -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,

View file

@ -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);
}

View file

@ -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 */

View file

@ -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;