mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 05:05:20 -05:00
Patch #5690 by Steve Bavin - Fix for memory corruption when using .talk clips
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10396 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
73c283e969
commit
30c618cd96
2 changed files with 50 additions and 10 deletions
56
apps/talk.c
56
apps/talk.c
|
|
@ -39,6 +39,23 @@
|
||||||
#include "playback.h"
|
#include "playback.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Memory layout varies between targets because the
|
||||||
|
Archos (MASCODEC) devices cannot mix voice and audio playback
|
||||||
|
|
||||||
|
MASCODEC | MASCODEC | SWCODEC
|
||||||
|
(playing) | (stopped) |
|
||||||
|
audiobuf-----------+-----------+-----------
|
||||||
|
audio | voice | thumbnail
|
||||||
|
|-----------|-----------
|
||||||
|
| thumbnail | voice
|
||||||
|
| |-----------
|
||||||
|
| | audio
|
||||||
|
audiobufend----------+-----------+-----------
|
||||||
|
|
||||||
|
SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */
|
||||||
|
|
||||||
|
|
||||||
/***************** Constants *****************/
|
/***************** Constants *****************/
|
||||||
|
|
||||||
#define QUEUE_SIZE 64 /* must be a power of two */
|
#define QUEUE_SIZE 64 /* must be a power of two */
|
||||||
|
|
@ -52,6 +69,10 @@ const char* const file_thumbnail_ext = ".talk";
|
||||||
|
|
||||||
#define LOADED_MASK 0x80000000 /* MSB */
|
#define LOADED_MASK 0x80000000 /* MSB */
|
||||||
|
|
||||||
|
#if CONFIG_CODEC == SWCODEC
|
||||||
|
#define MAX_THUMBNAIL_BUFSIZE 32768
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/***************** Data types *****************/
|
/***************** Data types *****************/
|
||||||
|
|
||||||
|
|
@ -172,12 +193,16 @@ static void load_voicefile(void)
|
||||||
if (((struct voicefile*)audiobuf)->table /* format check */
|
if (((struct voicefile*)audiobuf)->table /* format check */
|
||||||
== offsetof(struct voicefile, index))
|
== offsetof(struct voicefile, index))
|
||||||
{
|
{
|
||||||
|
#if CONFIG_CODEC == SWCODEC
|
||||||
|
/* SWCODEC: allocate permanent buffer */
|
||||||
|
p_voicefile = (struct voicefile*)buffer_alloc(file_size);
|
||||||
|
#else
|
||||||
|
/* MASCODEC: now use audiobuf for voice then thumbnail */
|
||||||
p_voicefile = (struct voicefile*)audiobuf;
|
p_voicefile = (struct voicefile*)audiobuf;
|
||||||
|
|
||||||
/* thumbnail buffer is the remaining space behind */
|
|
||||||
p_thumbnail = audiobuf + file_size;
|
p_thumbnail = audiobuf + file_size;
|
||||||
p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */
|
p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */
|
||||||
size_for_thumbnail = audiobufend - p_thumbnail;
|
size_for_thumbnail = audiobufend - p_thumbnail;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto load_err;
|
goto load_err;
|
||||||
|
|
@ -198,7 +223,7 @@ static void load_voicefile(void)
|
||||||
cpu_boost(true);
|
cpu_boost(true);
|
||||||
buf = (unsigned char *)(&p_voicefile->index) +
|
buf = (unsigned char *)(&p_voicefile->index) +
|
||||||
(p_voicefile->id1_max + p_voicefile->id2_max) * sizeof(struct clip_entry);
|
(p_voicefile->id1_max + p_voicefile->id2_max) * sizeof(struct clip_entry);
|
||||||
length = file_size - (buf - audiobuf);
|
length = file_size - (buf - (unsigned char *) p_voicefile);
|
||||||
|
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -216,7 +241,7 @@ static void load_voicefile(void)
|
||||||
load_size = (p_voicefile->id1_max + p_voicefile->id2_max)
|
load_size = (p_voicefile->id1_max + p_voicefile->id2_max)
|
||||||
* sizeof(struct clip_entry);
|
* sizeof(struct clip_entry);
|
||||||
got_size = read(filehandle,
|
got_size = read(filehandle,
|
||||||
audiobuf + offsetof(struct voicefile, index), load_size);
|
(unsigned char *) p_voicefile + offsetof(struct voicefile, index), load_size);
|
||||||
if (got_size != load_size) /* read error */
|
if (got_size != load_size) /* read error */
|
||||||
goto load_err;
|
goto load_err;
|
||||||
#else
|
#else
|
||||||
|
|
@ -278,9 +303,9 @@ re_check:
|
||||||
curr_hd[1] = p_lastclip[2];
|
curr_hd[1] = p_lastclip[2];
|
||||||
curr_hd[2] = p_lastclip[3];
|
curr_hd[2] = p_lastclip[3];
|
||||||
}
|
}
|
||||||
else if (p_silence != NULL /* silence clip available */
|
else if (p_silence != NULL /* silence clip available */
|
||||||
&& p_lastclip != p_silence /* previous clip wasn't silence */
|
&& p_lastclip != p_silence /* previous clip wasn't silence */
|
||||||
&& p_lastclip < p_thumbnail) /* ..and not a thumbnail */
|
&& p_lastclip != p_thumbnail) /* ..or thumbnail */
|
||||||
{ /* add silence clip when queue runs empty playing a voice clip */
|
{ /* add silence clip when queue runs empty playing a voice clip */
|
||||||
queue[queue_write].buf = p_silence;
|
queue[queue_write].buf = p_silence;
|
||||||
queue[queue_write].len = silence_len;
|
queue[queue_write].len = silence_len;
|
||||||
|
|
@ -424,7 +449,7 @@ static unsigned char* get_clip(long id, long* p_size)
|
||||||
clipsize = p_voicefile->index[id].size;
|
clipsize = p_voicefile->index[id].size;
|
||||||
if (clipsize == 0) /* clip not included in voicefile */
|
if (clipsize == 0) /* clip not included in voicefile */
|
||||||
return NULL;
|
return NULL;
|
||||||
clipbuf = audiobuf + p_voicefile->index[id].offset;
|
clipbuf = (unsigned char *) p_voicefile + p_voicefile->index[id].offset;
|
||||||
|
|
||||||
#ifdef HAVE_MMC /* dynamic loading, on demand */
|
#ifdef HAVE_MMC /* dynamic loading, on demand */
|
||||||
if (!(clipsize & LOADED_MASK))
|
if (!(clipsize & LOADED_MASK))
|
||||||
|
|
@ -451,8 +476,17 @@ static void reset_state(void)
|
||||||
{
|
{
|
||||||
queue_write = queue_read = 0; /* reset the queue */
|
queue_write = queue_read = 0; /* reset the queue */
|
||||||
p_voicefile = NULL; /* indicate no voicefile (trashed) */
|
p_voicefile = NULL; /* indicate no voicefile (trashed) */
|
||||||
p_thumbnail = audiobuf; /* whole space for thumbnail */
|
#if CONFIG_CODEC == SWCODEC
|
||||||
|
/* Allocate a dedicated thumbnail buffer */
|
||||||
size_for_thumbnail = audiobufend - audiobuf;
|
size_for_thumbnail = audiobufend - audiobuf;
|
||||||
|
if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE)
|
||||||
|
size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE;
|
||||||
|
p_thumbnail = buffer_alloc(size_for_thumbnail);
|
||||||
|
#else
|
||||||
|
/* Just use the audiobuf, without allocating anything */
|
||||||
|
p_thumbnail = audiobuf;
|
||||||
|
size_for_thumbnail = audiobufend - audiobuf;
|
||||||
|
#endif
|
||||||
p_silence = NULL; /* pause clip not accessible */
|
p_silence = NULL; /* pause clip not accessible */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,8 +597,10 @@ int talk_file(const char* filename, bool enqueue)
|
||||||
int size;
|
int size;
|
||||||
struct mp3entry info;
|
struct mp3entry info;
|
||||||
|
|
||||||
|
#if CONFIG_CODEC != SWCODEC
|
||||||
if (audio_status()) /* busy, buffer in use */
|
if (audio_status()) /* busy, buffer in use */
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (p_thumbnail == NULL || size_for_thumbnail <= 0)
|
if (p_thumbnail == NULL || size_for_thumbnail <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -587,7 +623,7 @@ int talk_file(const char* filename, bool enqueue)
|
||||||
|
|
||||||
/* ToDo: find audio, skip ID headers and trailers */
|
/* ToDo: find audio, skip ID headers and trailers */
|
||||||
|
|
||||||
if (size)
|
if (size != 0 && size != size_for_thumbnail) /* Don't play missing or truncated clips */
|
||||||
{
|
{
|
||||||
#if CONFIG_CODEC != SWCODEC
|
#if CONFIG_CODEC != SWCODEC
|
||||||
bitswap(p_thumbnail, size);
|
bitswap(p_thumbnail, size);
|
||||||
|
|
|
||||||
|
|
@ -1306,8 +1306,10 @@ int ft_play_dirname(char* name)
|
||||||
int fd;
|
int fd;
|
||||||
char dirname_mp3_filename[MAX_PATH+1];
|
char dirname_mp3_filename[MAX_PATH+1];
|
||||||
|
|
||||||
|
#if CONFIG_CODEC != SWCODEC
|
||||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
snprintf(dirname_mp3_filename, sizeof(dirname_mp3_filename), "%s/%s/%s",
|
snprintf(dirname_mp3_filename, sizeof(dirname_mp3_filename), "%s/%s/%s",
|
||||||
tc.currdir[1] ? tc.currdir : "" , name,
|
tc.currdir[1] ? tc.currdir : "" , name,
|
||||||
|
|
@ -1334,8 +1336,10 @@ void ft_play_filename(char *dir, char *file)
|
||||||
{
|
{
|
||||||
char name_mp3_filename[MAX_PATH+1];
|
char name_mp3_filename[MAX_PATH+1];
|
||||||
|
|
||||||
|
#if CONFIG_CODEC != SWCODEC
|
||||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)],
|
if (strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)],
|
||||||
file_thumbnail_ext))
|
file_thumbnail_ext))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue