forked from len0rd/rockbox
Add a "Speed test folder" option for batch testing. When this option is selected, all files in the same directory as the selected file will be tested, and the results written to a numbered log file in the root. Thanks to Jens for his screen+file logging functions I stole from test_disk.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13670 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
5b25a6e2df
commit
f01b661116
1 changed files with 226 additions and 110 deletions
|
@ -30,6 +30,52 @@ PLUGIN_HEADER
|
||||||
|
|
||||||
static struct plugin_api* rb;
|
static struct plugin_api* rb;
|
||||||
|
|
||||||
|
/* Log functions copied from test_disk.c */
|
||||||
|
static int line = 0;
|
||||||
|
static int max_line = 0;
|
||||||
|
static int log_fd = -1;
|
||||||
|
static char logfilename[MAX_PATH];
|
||||||
|
|
||||||
|
static bool log_init(bool use_logfile)
|
||||||
|
{
|
||||||
|
int h;
|
||||||
|
|
||||||
|
rb->lcd_setmargins(0, 0);
|
||||||
|
rb->lcd_getstringsize("A", NULL, &h);
|
||||||
|
max_line = LCD_HEIGHT / h;
|
||||||
|
line = 0;
|
||||||
|
rb->lcd_clear_display();
|
||||||
|
rb->lcd_update();
|
||||||
|
|
||||||
|
if (use_logfile) {
|
||||||
|
rb->create_numbered_filename(logfilename, "/", "test_codec_log_", ".txt",
|
||||||
|
2 IF_CNFN_NUM_(, NULL));
|
||||||
|
log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC);
|
||||||
|
return log_fd >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_text(char *text, bool advance)
|
||||||
|
{
|
||||||
|
rb->lcd_puts(0, line, text);
|
||||||
|
rb->lcd_update();
|
||||||
|
if (advance)
|
||||||
|
{
|
||||||
|
if (++line >= max_line)
|
||||||
|
line = 0;
|
||||||
|
if (log_fd >= 0)
|
||||||
|
rb->fdprintf(log_fd, "%s\n", text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_close(void)
|
||||||
|
{
|
||||||
|
if (log_fd >= 0)
|
||||||
|
rb->close(log_fd);
|
||||||
|
}
|
||||||
|
|
||||||
struct wavinfo_t
|
struct wavinfo_t
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -43,7 +89,7 @@ struct wavinfo_t
|
||||||
static void* audiobuf;
|
static void* audiobuf;
|
||||||
static void* codec_mallocbuf;
|
static void* codec_mallocbuf;
|
||||||
static size_t audiosize;
|
static size_t audiosize;
|
||||||
static char str[40];
|
static char str[MAX_PATH];
|
||||||
|
|
||||||
/* Our local implementation of the codec API */
|
/* Our local implementation of the codec API */
|
||||||
static struct codec_api ci;
|
static struct codec_api ci;
|
||||||
|
@ -149,6 +195,9 @@ static bool pcmbuf_insert_null(const void *ch1, const void *ch2, int count)
|
||||||
(void)ch2;
|
(void)ch2;
|
||||||
(void)count;
|
(void)count;
|
||||||
|
|
||||||
|
/* Prevent idle poweroff */
|
||||||
|
rb->reset_poweroff_timer();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +223,9 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count)
|
||||||
unsigned char* p = wavbuffer;
|
unsigned char* p = wavbuffer;
|
||||||
int scale = wavinfo.sampledepth - 15;
|
int scale = wavinfo.sampledepth - 15;
|
||||||
|
|
||||||
|
/* Prevent idle poweroff */
|
||||||
|
rb->reset_poweroff_timer();
|
||||||
|
|
||||||
if (wavinfo.sampledepth <= 16) {
|
if (wavinfo.sampledepth <= 16) {
|
||||||
data1_16 = ch1;
|
data1_16 = ch1;
|
||||||
data2_16 = ch2;
|
data2_16 = ch2;
|
||||||
|
@ -445,24 +497,145 @@ static void codec_thread(void)
|
||||||
rb->remove_thread(NULL);
|
rb->remove_thread(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* plugin entry point */
|
static unsigned char* codec_stack;
|
||||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
static size_t codec_stack_size;
|
||||||
|
|
||||||
|
static enum plugin_status test_track(char* filename)
|
||||||
{
|
{
|
||||||
size_t n;
|
size_t n;
|
||||||
int fd;
|
int fd;
|
||||||
int i;
|
|
||||||
enum plugin_status res = PLUGIN_OK;
|
enum plugin_status res = PLUGIN_OK;
|
||||||
unsigned long starttick;
|
unsigned long starttick;
|
||||||
unsigned long ticks;
|
unsigned long ticks;
|
||||||
unsigned long speed;
|
unsigned long speed;
|
||||||
unsigned long duration;
|
unsigned long duration;
|
||||||
unsigned char* codec_stack;
|
|
||||||
unsigned char* codec_stack_copy;
|
|
||||||
size_t codec_stack_size;
|
|
||||||
struct thread_entry* codecthread_id;
|
struct thread_entry* codecthread_id;
|
||||||
int result, selection = 0;
|
|
||||||
char* ch;
|
char* ch;
|
||||||
int line = 0;
|
|
||||||
|
/* Display filename (excluding any path)*/
|
||||||
|
ch = rb->strrchr(filename, '/');
|
||||||
|
if (ch==NULL)
|
||||||
|
ch = filename;
|
||||||
|
else
|
||||||
|
ch++;
|
||||||
|
|
||||||
|
rb->snprintf(str,sizeof(str),"%s",ch);
|
||||||
|
log_text(str,true);
|
||||||
|
|
||||||
|
log_text("Loading...",false);
|
||||||
|
|
||||||
|
fd = rb->open(filename,O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
log_text("Cannot open file",true);
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
track.filesize = rb->filesize(fd);
|
||||||
|
|
||||||
|
/* Clear the id3 struct */
|
||||||
|
rb->memset(&track.id3, 0, sizeof(struct mp3entry));
|
||||||
|
|
||||||
|
if (!rb->get_metadata(&track, fd, filename,
|
||||||
|
rb->global_settings->id3_v1_first))
|
||||||
|
{
|
||||||
|
log_text("Cannot read metadata",true);
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track.filesize > audiosize)
|
||||||
|
{
|
||||||
|
log_text("File too large",true);
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = rb->read(fd, audiobuf, track.filesize);
|
||||||
|
|
||||||
|
if (n != track.filesize)
|
||||||
|
{
|
||||||
|
log_text("Read failed.",true);
|
||||||
|
res = PLUGIN_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialise the function pointers in the codec API */
|
||||||
|
init_ci();
|
||||||
|
|
||||||
|
/* Prepare the codec struct for playing the whole file */
|
||||||
|
ci.filesize = track.filesize;
|
||||||
|
ci.id3 = &track.id3;
|
||||||
|
ci.taginfo_ready = &taginfo_ready;
|
||||||
|
ci.curpos = 0;
|
||||||
|
ci.stop_codec = false;
|
||||||
|
ci.new_track = 0;
|
||||||
|
ci.seek_time = 0;
|
||||||
|
|
||||||
|
starttick = *rb->current_tick;
|
||||||
|
|
||||||
|
codec_playing = true;
|
||||||
|
|
||||||
|
if ((codecthread_id = rb->create_thread(codec_thread,
|
||||||
|
(uint8_t*)codec_stack, codec_stack_size, "testcodec" IF_PRIO(,PRIORITY_PLAYBACK)
|
||||||
|
IF_COP(, CPU, false))) == NULL)
|
||||||
|
{
|
||||||
|
log_text("Cannot create codec thread!",true);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for codec thread to die */
|
||||||
|
while (codec_playing)
|
||||||
|
{
|
||||||
|
rb->sleep(HZ);
|
||||||
|
rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length);
|
||||||
|
log_text(str,false);
|
||||||
|
}
|
||||||
|
/* Save the current time before we spin up the disk to access the log */
|
||||||
|
ticks = *rb->current_tick - starttick;
|
||||||
|
|
||||||
|
log_text(str,true);
|
||||||
|
|
||||||
|
/* Close WAV file (if there was one) */
|
||||||
|
if (wavinfo.fd >= 0) {
|
||||||
|
close_wav();
|
||||||
|
log_text("Wrote /test.wav",true);
|
||||||
|
} else {
|
||||||
|
/* Display benchmark information */
|
||||||
|
rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100);
|
||||||
|
log_text(str,true);
|
||||||
|
|
||||||
|
duration = track.id3.length / 10;
|
||||||
|
rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100);
|
||||||
|
log_text(str,true);
|
||||||
|
|
||||||
|
if (ticks > 0)
|
||||||
|
speed = duration * 10000 / ticks;
|
||||||
|
else
|
||||||
|
speed = 0;
|
||||||
|
|
||||||
|
rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100);
|
||||||
|
log_text(str,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write an empty line to the log */
|
||||||
|
log_text("",true);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* plugin entry point */
|
||||||
|
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||||
|
{
|
||||||
|
unsigned char* codec_stack_copy;
|
||||||
|
int result, selection = 0;
|
||||||
|
enum plugin_status res = PLUGIN_OK;
|
||||||
|
int scandir;
|
||||||
|
int i;
|
||||||
|
struct dirent *entry;
|
||||||
|
DIR* dir;
|
||||||
|
char* ch;
|
||||||
|
char dirpath[MAX_PATH];
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
|
||||||
rb = api;
|
rb = api;
|
||||||
|
|
||||||
|
@ -506,43 +679,40 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||||
rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size);
|
rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fd = rb->open(parameter,O_RDONLY);
|
|
||||||
if (fd < 0)
|
|
||||||
{
|
|
||||||
rb->splash(HZ*2, "Cannot open file");
|
|
||||||
return PLUGIN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
track.filesize = rb->filesize(fd);
|
|
||||||
|
|
||||||
if (!rb->get_metadata(&track, fd, parameter,
|
|
||||||
rb->global_settings->id3_v1_first))
|
|
||||||
{
|
|
||||||
rb->splash(HZ*2, "Cannot read metadata");
|
|
||||||
return PLUGIN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (track.filesize > audiosize)
|
|
||||||
{
|
|
||||||
rb->splash(HZ*2, "File too large");
|
|
||||||
return PLUGIN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
rb->cpu_boost(true);
|
rb->cpu_boost(true);
|
||||||
#endif
|
#endif
|
||||||
rb->lcd_clear_display();
|
rb->lcd_clear_display();
|
||||||
rb->lcd_update();
|
rb->lcd_update();
|
||||||
|
|
||||||
MENUITEM_STRINGLIST(menu,"test_codec",NULL,"Speed test","Write WAV");
|
MENUITEM_STRINGLIST(
|
||||||
|
menu, "test_codec", NULL,
|
||||||
|
"Speed test",
|
||||||
|
"Speed test folder",
|
||||||
|
"Write WAV",
|
||||||
|
);
|
||||||
|
|
||||||
rb->lcd_clear_display();
|
rb->lcd_clear_display();
|
||||||
|
|
||||||
result=rb->do_menu(&menu,&selection);
|
result=rb->do_menu(&menu,&selection);
|
||||||
|
|
||||||
|
scandir = 0;
|
||||||
|
|
||||||
if (result==0) {
|
if (result==0) {
|
||||||
wavinfo.fd = -1;
|
wavinfo.fd = -1;
|
||||||
|
log_init(false);
|
||||||
} else if (result==1) {
|
} else if (result==1) {
|
||||||
|
wavinfo.fd = -1;
|
||||||
|
scandir = 1;
|
||||||
|
|
||||||
|
/* Only create a log file when we are testing a folder */
|
||||||
|
if (!log_init(true)) {
|
||||||
|
rb->splash(HZ*2, "Cannot create logfile");
|
||||||
|
res = PLUGIN_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
} else if (result==2) {
|
||||||
|
log_init(false);
|
||||||
init_wav("/test.wav");
|
init_wav("/test.wav");
|
||||||
if (wavinfo.fd < 0) {
|
if (wavinfo.fd < 0) {
|
||||||
rb->splash(HZ*2, "Cannot create /test.wav");
|
rb->splash(HZ*2, "Cannot create /test.wav");
|
||||||
|
@ -557,92 +727,38 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb->lcd_clear_display();
|
if (scandir) {
|
||||||
rb->splash(0, "Loading...");
|
/* Test all files in the same directory as the file selected by the
|
||||||
rb->lcd_clear_display();
|
user */
|
||||||
|
|
||||||
n = rb->read(fd, audiobuf, track.filesize);
|
rb->strncpy(dirpath,parameter,sizeof(dirpath));
|
||||||
|
ch = rb->strrchr(dirpath,'/');
|
||||||
|
ch[1]=0;
|
||||||
|
|
||||||
if (n != track.filesize)
|
DEBUGF("Scanning directory \"%s\"\n",dirpath);
|
||||||
{
|
dir = rb->opendir(dirpath);
|
||||||
rb->splash(HZ*2, "Read failed.");
|
if (dir) {
|
||||||
res = PLUGIN_ERROR;
|
entry = rb->readdir(dir);
|
||||||
goto exit;
|
while (entry) {
|
||||||
}
|
if (!(entry->attribute & ATTR_DIRECTORY)) {
|
||||||
|
rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name);
|
||||||
|
test_track(filename);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialise the function pointers in the codec API */
|
/* Read next entry */
|
||||||
init_ci();
|
entry = rb->readdir(dir);
|
||||||
|
}
|
||||||
/* Prepare the codec struct for playing the whole file */
|
}
|
||||||
ci.filesize = track.filesize;
|
|
||||||
ci.id3 = &track.id3;
|
|
||||||
ci.taginfo_ready = &taginfo_ready;
|
|
||||||
ci.curpos = 0;
|
|
||||||
ci.stop_codec = false;
|
|
||||||
ci.new_track = 0;
|
|
||||||
ci.seek_time = 0;
|
|
||||||
|
|
||||||
starttick = *rb->current_tick;
|
|
||||||
|
|
||||||
codec_playing = true;
|
|
||||||
|
|
||||||
if ((codecthread_id = rb->create_thread(codec_thread,
|
|
||||||
(uint8_t*)codec_stack, codec_stack_size, "testcodec" IF_PRIO(,PRIORITY_PLAYBACK)
|
|
||||||
IF_COP(, CPU, false))) == NULL)
|
|
||||||
{
|
|
||||||
rb->splash(HZ, "Cannot create codec thread!");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Display filename (excluding any path)*/
|
|
||||||
ch = rb->strrchr(parameter, '/');
|
|
||||||
if (ch==NULL)
|
|
||||||
ch = parameter;
|
|
||||||
else
|
|
||||||
ch++;
|
|
||||||
|
|
||||||
rb->snprintf(str,sizeof(str),"%s",ch);
|
|
||||||
rb->lcd_puts(0,line++,str);
|
|
||||||
|
|
||||||
/* Wait for codec thread to die */
|
|
||||||
while (codec_playing)
|
|
||||||
{
|
|
||||||
rb->sleep(HZ);
|
|
||||||
rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length);
|
|
||||||
rb->lcd_puts(0,line,str);
|
|
||||||
rb->lcd_update();
|
|
||||||
}
|
|
||||||
line++;
|
|
||||||
|
|
||||||
/* Close WAV file (if there was one) */
|
|
||||||
if (wavinfo.fd >= 0) {
|
|
||||||
close_wav();
|
|
||||||
rb->lcd_puts(0,line++,"Wrote /test.wav");
|
|
||||||
} else {
|
} else {
|
||||||
/* Display benchmark information */
|
/* Just test the file */
|
||||||
|
res = test_track(parameter);
|
||||||
ticks = *rb->current_tick - starttick;
|
|
||||||
rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100);
|
|
||||||
rb->lcd_puts(0,line++,str);
|
|
||||||
|
|
||||||
duration = track.id3.length / 10;
|
|
||||||
rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100);
|
|
||||||
rb->lcd_puts(0,line++,str);
|
|
||||||
|
|
||||||
if (ticks > 0)
|
|
||||||
speed = duration * 10000 / ticks;
|
|
||||||
else
|
|
||||||
speed = 0;
|
|
||||||
|
|
||||||
rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100);
|
|
||||||
rb->lcd_puts(0,line++,str);
|
|
||||||
|
|
||||||
|
while (rb->button_get(true) != TESTCODEC_EXITBUTTON);
|
||||||
}
|
}
|
||||||
rb->lcd_update();
|
|
||||||
|
|
||||||
while (rb->button_get(true) != TESTCODEC_EXITBUTTON);
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
log_close();
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
/* Restore the codec thread's stack */
|
/* Restore the codec thread's stack */
|
||||||
rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size);
|
rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue