diff options
author | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-05-09 18:18:05 +0000 |
---|---|---|
committer | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-05-09 18:18:05 +0000 |
commit | 12deda14d512f3d39ccbb6980022714971e1297f (patch) | |
tree | dd6b1a2daf341218df1ab16158a8bbf0c2796490 /apps/plugins | |
parent | 2fef5b7b4a3ab4224de48a5c32b6fb1ae27b5266 (diff) | |
download | rockbox-12deda14d512f3d39ccbb6980022714971e1297f.tar.gz rockbox-12deda14d512f3d39ccbb6980022714971e1297f.zip |
adaptive spinup control
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4599 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/video.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/apps/plugins/video.c b/apps/plugins/video.c index ce7611d389..3e40f9af9c 100644 --- a/apps/plugins/video.c +++ b/apps/plugins/video.c | |||
@@ -43,8 +43,8 @@ | |||
43 | #define FF_TICKS 3000; // experimentally found nice | 43 | #define FF_TICKS 3000; // experimentally found nice |
44 | 44 | ||
45 | // trigger levels, we need about 80 kB/sec | 45 | // trigger levels, we need about 80 kB/sec |
46 | #define PRECHARGE (1024 * 64) // the initial filling before starting to play | 46 | #define SPINUP_INIT 5000 // from what level on to refill, in milliseconds |
47 | #define SPINUP 3300 // from what level on to refill, in milliseconds | 47 | #define SPINUP_SAFETY 700 // how much on top of the measured spinup time |
48 | #define CHUNK (1024*32) // read size | 48 | #define CHUNK (1024*32) // read size |
49 | 49 | ||
50 | 50 | ||
@@ -148,6 +148,7 @@ static struct | |||
148 | bool bSeeking; | 148 | bool bSeeking; |
149 | int nSeekAcc; // accelleration value for seek | 149 | int nSeekAcc; // accelleration value for seek |
150 | int nSeekPos; // current file position for seek | 150 | int nSeekPos; // current file position for seek |
151 | bool bDiskSleep; // disk is suspended | ||
151 | } gPlay; | 152 | } gPlay; |
152 | 153 | ||
153 | // buffer information | 154 | // buffer information |
@@ -166,6 +167,7 @@ static struct | |||
166 | bool bEOF; // flag for end of file | 167 | bool bEOF; // flag for end of file |
167 | int low_water; // reload threshold | 168 | int low_water; // reload threshold |
168 | int high_water; // end of reload threshold | 169 | int high_water; // end of reload threshold |
170 | int spinup_safety; // safety margin when recalculating low_water | ||
169 | int nReadChunk; // how much data for normal buffer fill | 171 | int nReadChunk; // how much data for normal buffer fill |
170 | int nSeekChunk; // how much data while seeking | 172 | int nSeekChunk; // how much data while seeking |
171 | } gBuf; | 173 | } gBuf; |
@@ -177,6 +179,8 @@ static struct | |||
177 | int minVideoAvail; | 179 | int minVideoAvail; |
178 | int nAudioUnderruns; | 180 | int nAudioUnderruns; |
179 | int nVideoUnderruns; | 181 | int nVideoUnderruns; |
182 | long minSpinup; | ||
183 | long maxSpinup; | ||
180 | } gStats; | 184 | } gStats; |
181 | 185 | ||
182 | tFileHeader gFileHdr; // file header | 186 | tFileHeader gFileHdr; // file header |
@@ -485,8 +489,8 @@ int SeekTo(int fd, int nPos) | |||
485 | gBuf.pBufFill = gBuf.pBufStart; // all empty | 489 | gBuf.pBufFill = gBuf.pBufStart; // all empty |
486 | gBuf.pReadVideo = gBuf.pReadAudio = gBuf.pBufStart; | 490 | gBuf.pReadVideo = gBuf.pReadAudio = gBuf.pBufStart; |
487 | 491 | ||
488 | read_now = (PRECHARGE + gBuf.granularity - 1); // round up | 492 | read_now = gBuf.low_water - 1; // less than low water, so loading will continue |
489 | read_now -= read_now % gBuf.granularity; // to granularity | 493 | read_now -= read_now % gBuf.granularity; // round down to granularity |
490 | got_now = rb->read(fd, gBuf.pBufFill, read_now); | 494 | got_now = rb->read(fd, gBuf.pBufFill, read_now); |
491 | gBuf.bEOF = (read_now != got_now); | 495 | gBuf.bEOF = (read_now != got_now); |
492 | gBuf.pBufFill += got_now; | 496 | gBuf.pBufFill += got_now; |
@@ -574,6 +578,7 @@ int PlayTick(int fd) | |||
574 | { // refill buffer | 578 | { // refill buffer |
575 | int read_now, got_now; | 579 | int read_now, got_now; |
576 | int buf_free; | 580 | int buf_free; |
581 | long spinup; // measure the spinup time | ||
577 | 582 | ||
578 | // how much can we reload, don't fill completely, would appear empty | 583 | // how much can we reload, don't fill completely, would appear empty |
579 | buf_free = gBuf.bufsize - MAX(avail_audio, avail_video) - gBuf.high_water; | 584 | buf_free = gBuf.bufsize - MAX(avail_audio, avail_video) - gBuf.high_water; |
@@ -590,6 +595,8 @@ int PlayTick(int fd) | |||
590 | if (read_now == buf_free) | 595 | if (read_now == buf_free) |
591 | gPlay.bRefilling = false; // last piece requested | 596 | gPlay.bRefilling = false; // last piece requested |
592 | 597 | ||
598 | spinup = *rb->current_tick; // in case this is interesting below | ||
599 | |||
593 | got_now = rb->read(fd, gBuf.pBufFill, read_now); | 600 | got_now = rb->read(fd, gBuf.pBufFill, read_now); |
594 | if (got_now != read_now || read_now == 0) | 601 | if (got_now != read_now || read_now == 0) |
595 | { | 602 | { |
@@ -597,10 +604,25 @@ int PlayTick(int fd) | |||
597 | gPlay.bRefilling = false; | 604 | gPlay.bRefilling = false; |
598 | } | 605 | } |
599 | 606 | ||
607 | if (gPlay.bDiskSleep) // statistics about the spinup time | ||
608 | { | ||
609 | spinup = *rb->current_tick - spinup; | ||
610 | gPlay.bDiskSleep = false; | ||
611 | if (spinup > gStats.maxSpinup) | ||
612 | gStats.maxSpinup = spinup; | ||
613 | if (spinup < gStats.minSpinup) | ||
614 | gStats.minSpinup = spinup; | ||
615 | |||
616 | // recalculate the low water mark from real measurements | ||
617 | gBuf.low_water = (gStats.maxSpinup + gBuf.spinup_safety) | ||
618 | * gFileHdr.bps_peak / 8 / HZ; | ||
619 | } | ||
620 | |||
600 | if (!gPlay.bRefilling | 621 | if (!gPlay.bRefilling |
601 | && rb->global_settings->disk_spindown < 20) // condition for test only | 622 | && rb->global_settings->disk_spindown < 20) // condition for test only |
602 | { | 623 | { |
603 | rb->ata_sleep(); // no point in leaving the disk run til timeout | 624 | rb->ata_sleep(); // no point in leaving the disk run til timeout |
625 | gPlay.bDiskSleep = true; | ||
604 | } | 626 | } |
605 | 627 | ||
606 | gBuf.pBufFill += got_now; | 628 | gBuf.pBufFill += got_now; |
@@ -749,6 +771,7 @@ int PlayTick(int fd) | |||
749 | 771 | ||
750 | if ((gPlay.bAudioUnderrun || gPlay.bVideoUnderrun) && !gBuf.bEOF) | 772 | if ((gPlay.bAudioUnderrun || gPlay.bVideoUnderrun) && !gBuf.bEOF) |
751 | { | 773 | { |
774 | gBuf.spinup_safety += HZ/2; // add extra spinup time for the future | ||
752 | filepos = rb->lseek(fd, 0, SEEK_CUR); | 775 | filepos = rb->lseek(fd, 0, SEEK_CUR); |
753 | 776 | ||
754 | if (gPlay.bHasVideo && gPlay.bVideoUnderrun) | 777 | if (gPlay.bHasVideo && gPlay.bVideoUnderrun) |
@@ -786,6 +809,7 @@ int main(char* filename) | |||
786 | // init statistics | 809 | // init statistics |
787 | rb->memset(&gStats, 0, sizeof(gStats)); | 810 | rb->memset(&gStats, 0, sizeof(gStats)); |
788 | gStats.minAudioAvail = gStats.minVideoAvail = INT_MAX; | 811 | gStats.minAudioAvail = gStats.minVideoAvail = INT_MAX; |
812 | gStats.minSpinup = INT_MAX; | ||
789 | 813 | ||
790 | // init playback state | 814 | // init playback state |
791 | rb->memset(&gPlay, 0, sizeof(gPlay)); | 815 | rb->memset(&gPlay, 0, sizeof(gPlay)); |
@@ -827,7 +851,8 @@ int main(char* filename) | |||
827 | gBuf.granularity *= 2; | 851 | gBuf.granularity *= 2; |
828 | gBuf.bufsize -= gBuf.bufsize % gBuf.granularity; // round down | 852 | gBuf.bufsize -= gBuf.bufsize % gBuf.granularity; // round down |
829 | gBuf.pBufEnd = gBuf.pBufStart + gBuf.bufsize; | 853 | gBuf.pBufEnd = gBuf.pBufStart + gBuf.bufsize; |
830 | gBuf.low_water = SPINUP * gFileHdr.bps_peak / 8000; | 854 | gBuf.low_water = SPINUP_INIT * gFileHdr.bps_peak / 8000; |
855 | gBuf.spinup_safety = SPINUP_SAFETY * HZ / 1000; // in time ticks | ||
831 | if (gFileHdr.audio_min_associated < 0) | 856 | if (gFileHdr.audio_min_associated < 0) |
832 | gBuf.high_water = 0 - gFileHdr.audio_min_associated; | 857 | gBuf.high_water = 0 - gFileHdr.audio_min_associated; |
833 | else | 858 | else |
@@ -897,9 +922,9 @@ int main(char* filename) | |||
897 | rb->lcd_puts(0, 2, gPrint); | 922 | rb->lcd_puts(0, 2, gPrint); |
898 | rb->snprintf(gPrint, sizeof(gPrint), "%d MinVideo bytes", gStats.minVideoAvail); | 923 | rb->snprintf(gPrint, sizeof(gPrint), "%d MinVideo bytes", gStats.minVideoAvail); |
899 | rb->lcd_puts(0, 3, gPrint); | 924 | rb->lcd_puts(0, 3, gPrint); |
900 | rb->snprintf(gPrint, sizeof(gPrint), "ReadChunk: %d", gBuf.nReadChunk); | 925 | rb->snprintf(gPrint, sizeof(gPrint), "MinSpinup %d.%02d", gStats.minSpinup/HZ, gStats.minSpinup%HZ); |
901 | rb->lcd_puts(0, 4, gPrint); | 926 | rb->lcd_puts(0, 4, gPrint); |
902 | rb->snprintf(gPrint, sizeof(gPrint), "SeekChunk: %d", gBuf.nSeekChunk); | 927 | rb->snprintf(gPrint, sizeof(gPrint), "MaxSpinup %d.%02d", gStats.maxSpinup/HZ, gStats.maxSpinup%HZ); |
903 | rb->lcd_puts(0, 5, gPrint); | 928 | rb->lcd_puts(0, 5, gPrint); |
904 | rb->snprintf(gPrint, sizeof(gPrint), "LowWater: %d", gBuf.low_water); | 929 | rb->snprintf(gPrint, sizeof(gPrint), "LowWater: %d", gBuf.low_water); |
905 | rb->lcd_puts(0, 6, gPrint); | 930 | rb->lcd_puts(0, 6, gPrint); |