summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2007-06-19 00:25:36 +0000
committerDave Chapman <dave@dchapman.com>2007-06-19 00:25:36 +0000
commitf01b661116f7fb469197deb5de6fbdbd5d3daee2 (patch)
treecd5a3a6da3a89d3e0ef1103caa86fde3ab306bcf
parent5b25a6e2dfaa4a336a5690935db5b7eadba971c5 (diff)
downloadrockbox-f01b661116f7fb469197deb5de6fbdbd5d3daee2.tar.gz
rockbox-f01b661116f7fb469197deb5de6fbdbd5d3daee2.zip
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
-rw-r--r--apps/plugins/test_codec.c332
1 files changed, 224 insertions, 108 deletions
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c
index de3746bb29..446bffb8a1 100644
--- a/apps/plugins/test_codec.c
+++ b/apps/plugins/test_codec.c
@@ -30,6 +30,52 @@ PLUGIN_HEADER
30 30
31static struct plugin_api* rb; 31static struct plugin_api* rb;
32 32
33/* Log functions copied from test_disk.c */
34static int line = 0;
35static int max_line = 0;
36static int log_fd = -1;
37static char logfilename[MAX_PATH];
38
39static bool log_init(bool use_logfile)
40{
41 int h;
42
43 rb->lcd_setmargins(0, 0);
44 rb->lcd_getstringsize("A", NULL, &h);
45 max_line = LCD_HEIGHT / h;
46 line = 0;
47 rb->lcd_clear_display();
48 rb->lcd_update();
49
50 if (use_logfile) {
51 rb->create_numbered_filename(logfilename, "/", "test_codec_log_", ".txt",
52 2 IF_CNFN_NUM_(, NULL));
53 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC);
54 return log_fd >= 0;
55 }
56
57 return true;
58}
59
60static void log_text(char *text, bool advance)
61{
62 rb->lcd_puts(0, line, text);
63 rb->lcd_update();
64 if (advance)
65 {
66 if (++line >= max_line)
67 line = 0;
68 if (log_fd >= 0)
69 rb->fdprintf(log_fd, "%s\n", text);
70 }
71}
72
73static void log_close(void)
74{
75 if (log_fd >= 0)
76 rb->close(log_fd);
77}
78
33struct wavinfo_t 79struct wavinfo_t
34{ 80{
35 int fd; 81 int fd;
@@ -43,7 +89,7 @@ struct wavinfo_t
43static void* audiobuf; 89static void* audiobuf;
44static void* codec_mallocbuf; 90static void* codec_mallocbuf;
45static size_t audiosize; 91static size_t audiosize;
46static char str[40]; 92static char str[MAX_PATH];
47 93
48/* Our local implementation of the codec API */ 94/* Our local implementation of the codec API */
49static struct codec_api ci; 95static struct codec_api ci;
@@ -149,6 +195,9 @@ static bool pcmbuf_insert_null(const void *ch1, const void *ch2, int count)
149 (void)ch2; 195 (void)ch2;
150 (void)count; 196 (void)count;
151 197
198 /* Prevent idle poweroff */
199 rb->reset_poweroff_timer();
200
152 return true; 201 return true;
153} 202}
154 203
@@ -174,6 +223,9 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count)
174 unsigned char* p = wavbuffer; 223 unsigned char* p = wavbuffer;
175 int scale = wavinfo.sampledepth - 15; 224 int scale = wavinfo.sampledepth - 15;
176 225
226 /* Prevent idle poweroff */
227 rb->reset_poweroff_timer();
228
177 if (wavinfo.sampledepth <= 16) { 229 if (wavinfo.sampledepth <= 16) {
178 data1_16 = ch1; 230 data1_16 = ch1;
179 data2_16 = ch2; 231 data2_16 = ch2;
@@ -445,127 +497,63 @@ static void codec_thread(void)
445 rb->remove_thread(NULL); 497 rb->remove_thread(NULL);
446} 498}
447 499
448/* plugin entry point */ 500static unsigned char* codec_stack;
449enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 501static size_t codec_stack_size;
502
503static enum plugin_status test_track(char* filename)
450{ 504{
451 size_t n; 505 size_t n;
452 int fd; 506 int fd;
453 int i;
454 enum plugin_status res = PLUGIN_OK; 507 enum plugin_status res = PLUGIN_OK;
455 unsigned long starttick; 508 unsigned long starttick;
456 unsigned long ticks; 509 unsigned long ticks;
457 unsigned long speed; 510 unsigned long speed;
458 unsigned long duration; 511 unsigned long duration;
459 unsigned char* codec_stack;
460 unsigned char* codec_stack_copy;
461 size_t codec_stack_size;
462 struct thread_entry* codecthread_id; 512 struct thread_entry* codecthread_id;
463 int result, selection = 0;
464 char* ch; 513 char* ch;
465 int line = 0;
466
467 rb = api;
468
469 if (parameter == NULL)
470 {
471 rb->splash(HZ*2, "No File");
472 return PLUGIN_ERROR;
473 }
474
475#ifdef SIMULATOR
476 /* The simulator thread implementation doesn't have stack buffers */
477 (void)i;
478 codec_stack_size = 0;
479#else
480 /* Borrow the codec thread's stack (in IRAM on most targets) */
481 codec_stack = NULL;
482 for (i = 0; i < MAXTHREADS; i++)
483 {
484 if (rb->strcmp(rb->threads[i].name,"codec")==0)
485 {
486 codec_stack = rb->threads[i].stack;
487 codec_stack_size = rb->threads[i].stack_size;
488 break;
489 }
490 }
491 514
492 if (codec_stack == NULL) 515 /* Display filename (excluding any path)*/
493 { 516 ch = rb->strrchr(filename, '/');
494 rb->splash(HZ*2, "No codec thread!"); 517 if (ch==NULL)
495 return PLUGIN_ERROR; 518 ch = filename;
496 } 519 else
497#endif 520 ch++;
498 521
499 codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); 522 rb->snprintf(str,sizeof(str),"%s",ch);
500 codec_stack_copy = codec_mallocbuf + 512*1024; 523 log_text(str,true);
501 audiobuf = codec_stack_copy + codec_stack_size;
502 audiosize -= 512*1024 + codec_stack_size;
503 524
504#ifndef SIMULATOR 525 log_text("Loading...",false);
505 /* Backup the codec thread's stack */
506 rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size);
507#endif
508 526
509 fd = rb->open(parameter,O_RDONLY); 527 fd = rb->open(filename,O_RDONLY);
510 if (fd < 0) 528 if (fd < 0)
511 { 529 {
512 rb->splash(HZ*2, "Cannot open file"); 530 log_text("Cannot open file",true);
513 return PLUGIN_ERROR; 531 return PLUGIN_ERROR;
514 } 532 }
515 533
516 track.filesize = rb->filesize(fd); 534 track.filesize = rb->filesize(fd);
517 535
518 if (!rb->get_metadata(&track, fd, parameter, 536 /* Clear the id3 struct */
537 rb->memset(&track.id3, 0, sizeof(struct mp3entry));
538
539 if (!rb->get_metadata(&track, fd, filename,
519 rb->global_settings->id3_v1_first)) 540 rb->global_settings->id3_v1_first))
520 { 541 {
521 rb->splash(HZ*2, "Cannot read metadata"); 542 log_text("Cannot read metadata",true);
522 return PLUGIN_ERROR; 543 return PLUGIN_ERROR;
523 } 544 }
524 545
525 if (track.filesize > audiosize) 546 if (track.filesize > audiosize)
526 { 547 {
527 rb->splash(HZ*2, "File too large"); 548 log_text("File too large",true);
528 return PLUGIN_ERROR; 549 return PLUGIN_ERROR;
529 } 550 }
530 551
531#ifdef HAVE_ADJUSTABLE_CPU_FREQ
532 rb->cpu_boost(true);
533#endif
534 rb->lcd_clear_display();
535 rb->lcd_update();
536
537 MENUITEM_STRINGLIST(menu,"test_codec",NULL,"Speed test","Write WAV");
538
539 rb->lcd_clear_display();
540
541 result=rb->do_menu(&menu,&selection);
542
543 if (result==0) {
544 wavinfo.fd = -1;
545 } else if (result==1) {
546 init_wav("/test.wav");
547 if (wavinfo.fd < 0) {
548 rb->splash(HZ*2, "Cannot create /test.wav");
549 res = PLUGIN_ERROR;
550 goto exit;
551 }
552 } else if (result == MENU_ATTACHED_USB) {
553 res = PLUGIN_USB_CONNECTED;
554 goto exit;
555 } else if (result < 0) {
556 res = PLUGIN_OK;
557 goto exit;
558 }
559
560 rb->lcd_clear_display();
561 rb->splash(0, "Loading...");
562 rb->lcd_clear_display();
563
564 n = rb->read(fd, audiobuf, track.filesize); 552 n = rb->read(fd, audiobuf, track.filesize);
565 553
566 if (n != track.filesize) 554 if (n != track.filesize)
567 { 555 {
568 rb->splash(HZ*2, "Read failed."); 556 log_text("Read failed.",true);
569 res = PLUGIN_ERROR; 557 res = PLUGIN_ERROR;
570 goto exit; 558 goto exit;
571 } 559 }
@@ -590,44 +578,34 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
590 (uint8_t*)codec_stack, codec_stack_size, "testcodec" IF_PRIO(,PRIORITY_PLAYBACK) 578 (uint8_t*)codec_stack, codec_stack_size, "testcodec" IF_PRIO(,PRIORITY_PLAYBACK)
591 IF_COP(, CPU, false))) == NULL) 579 IF_COP(, CPU, false))) == NULL)
592 { 580 {
593 rb->splash(HZ, "Cannot create codec thread!"); 581 log_text("Cannot create codec thread!",true);
594 goto exit; 582 goto exit;
595 } 583 }
596 584
597 /* Display filename (excluding any path)*/
598 ch = rb->strrchr(parameter, '/');
599 if (ch==NULL)
600 ch = parameter;
601 else
602 ch++;
603
604 rb->snprintf(str,sizeof(str),"%s",ch);
605 rb->lcd_puts(0,line++,str);
606
607 /* Wait for codec thread to die */ 585 /* Wait for codec thread to die */
608 while (codec_playing) 586 while (codec_playing)
609 { 587 {
610 rb->sleep(HZ); 588 rb->sleep(HZ);
611 rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length); 589 rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length);
612 rb->lcd_puts(0,line,str); 590 log_text(str,false);
613 rb->lcd_update();
614 } 591 }
615 line++; 592 /* Save the current time before we spin up the disk to access the log */
593 ticks = *rb->current_tick - starttick;
594
595 log_text(str,true);
616 596
617 /* Close WAV file (if there was one) */ 597 /* Close WAV file (if there was one) */
618 if (wavinfo.fd >= 0) { 598 if (wavinfo.fd >= 0) {
619 close_wav(); 599 close_wav();
620 rb->lcd_puts(0,line++,"Wrote /test.wav"); 600 log_text("Wrote /test.wav",true);
621 } else { 601 } else {
622 /* Display benchmark information */ 602 /* Display benchmark information */
623
624 ticks = *rb->current_tick - starttick;
625 rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100); 603 rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100);
626 rb->lcd_puts(0,line++,str); 604 log_text(str,true);
627 605
628 duration = track.id3.length / 10; 606 duration = track.id3.length / 10;
629 rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100); 607 rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100);
630 rb->lcd_puts(0,line++,str); 608 log_text(str,true);
631 609
632 if (ticks > 0) 610 if (ticks > 0)
633 speed = duration * 10000 / ticks; 611 speed = duration * 10000 / ticks;
@@ -635,14 +613,152 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
635 speed = 0; 613 speed = 0;
636 614
637 rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100); 615 rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100);
638 rb->lcd_puts(0,line++,str); 616 log_text(str,true);
617 }
618
619 /* Write an empty line to the log */
620 log_text("",true);
621
622exit:
623 return res;
624}
625
626/* plugin entry point */
627enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
628{
629 unsigned char* codec_stack_copy;
630 int result, selection = 0;
631 enum plugin_status res = PLUGIN_OK;
632 int scandir;
633 int i;
634 struct dirent *entry;
635 DIR* dir;
636 char* ch;
637 char dirpath[MAX_PATH];
638 char filename[MAX_PATH];
639
640 rb = api;
639 641
642 if (parameter == NULL)
643 {
644 rb->splash(HZ*2, "No File");
645 return PLUGIN_ERROR;
646 }
647
648#ifdef SIMULATOR
649 /* The simulator thread implementation doesn't have stack buffers */
650 (void)i;
651 codec_stack_size = 0;
652#else
653 /* Borrow the codec thread's stack (in IRAM on most targets) */
654 codec_stack = NULL;
655 for (i = 0; i < MAXTHREADS; i++)
656 {
657 if (rb->strcmp(rb->threads[i].name,"codec")==0)
658 {
659 codec_stack = rb->threads[i].stack;
660 codec_stack_size = rb->threads[i].stack_size;
661 break;
662 }
663 }
664
665 if (codec_stack == NULL)
666 {
667 rb->splash(HZ*2, "No codec thread!");
668 return PLUGIN_ERROR;
640 } 669 }
670#endif
671
672 codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize);
673 codec_stack_copy = codec_mallocbuf + 512*1024;
674 audiobuf = codec_stack_copy + codec_stack_size;
675 audiosize -= 512*1024 + codec_stack_size;
676
677#ifndef SIMULATOR
678 /* Backup the codec thread's stack */
679 rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size);
680#endif
681
682#ifdef HAVE_ADJUSTABLE_CPU_FREQ
683 rb->cpu_boost(true);
684#endif
685 rb->lcd_clear_display();
641 rb->lcd_update(); 686 rb->lcd_update();
642 687
643 while (rb->button_get(true) != TESTCODEC_EXITBUTTON); 688 MENUITEM_STRINGLIST(
689 menu, "test_codec", NULL,
690 "Speed test",
691 "Speed test folder",
692 "Write WAV",
693 );
694
695 rb->lcd_clear_display();
696
697 result=rb->do_menu(&menu,&selection);
698
699 scandir = 0;
700
701 if (result==0) {
702 wavinfo.fd = -1;
703 log_init(false);
704 } else if (result==1) {
705 wavinfo.fd = -1;
706 scandir = 1;
707
708 /* Only create a log file when we are testing a folder */
709 if (!log_init(true)) {
710 rb->splash(HZ*2, "Cannot create logfile");
711 res = PLUGIN_ERROR;
712 goto exit;
713 }
714 } else if (result==2) {
715 log_init(false);
716 init_wav("/test.wav");
717 if (wavinfo.fd < 0) {
718 rb->splash(HZ*2, "Cannot create /test.wav");
719 res = PLUGIN_ERROR;
720 goto exit;
721 }
722 } else if (result == MENU_ATTACHED_USB) {
723 res = PLUGIN_USB_CONNECTED;
724 goto exit;
725 } else if (result < 0) {
726 res = PLUGIN_OK;
727 goto exit;
728 }
729
730 if (scandir) {
731 /* Test all files in the same directory as the file selected by the
732 user */
733
734 rb->strncpy(dirpath,parameter,sizeof(dirpath));
735 ch = rb->strrchr(dirpath,'/');
736 ch[1]=0;
737
738 DEBUGF("Scanning directory \"%s\"\n",dirpath);
739 dir = rb->opendir(dirpath);
740 if (dir) {
741 entry = rb->readdir(dir);
742 while (entry) {
743 if (!(entry->attribute & ATTR_DIRECTORY)) {
744 rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name);
745 test_track(filename);
746 }
747
748 /* Read next entry */
749 entry = rb->readdir(dir);
750 }
751 }
752 } else {
753 /* Just test the file */
754 res = test_track(parameter);
755
756 while (rb->button_get(true) != TESTCODEC_EXITBUTTON);
757 }
644 758
645exit: 759exit:
760 log_close();
761
646#ifndef SIMULATOR 762#ifndef SIMULATOR
647 /* Restore the codec thread's stack */ 763 /* Restore the codec thread's stack */
648 rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size); 764 rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size);