1
0
Fork 0
forked from len0rd/rockbox

Codecs: mpa: Improve seek in large mp3 vbr files

Use current position as toc mark and use it if it gives better accuracy.

Continuation of 3883c978

Change-Id: Ic6e8192fc43061f3c07128486dbefba7382be5ce
This commit is contained in:
Roman Artiukhin 2024-01-24 11:40:51 +02:00
parent 49910eca4b
commit 1122cae028

View file

@ -176,6 +176,8 @@ static int get_file_pos(int newtime)
struct mp3entry *id3 = ci->id3; struct mp3entry *id3 = ci->id3;
if (id3->vbr) { if (id3->vbr) {
int curpos = ci->curpos - id3->first_frame_offset;
long skipms_from_curpos = curpos > 0 ? (long) (id3->elapsed - newtime) : - newtime;
if (id3->has_toc) { if (id3->has_toc) {
/* Use the TOC to find the new position */ /* Use the TOC to find the new position */
unsigned int percent = ((uint64_t)newtime * 100) / id3->length; unsigned int percent = ((uint64_t)newtime * 100) / id3->length;
@ -183,28 +185,29 @@ static int get_file_pos(int newtime)
percent = 99; percent = 99;
unsigned int pct_timestep = id3->length / 100; unsigned int pct_timestep = id3->length / 100;
unsigned int toc_sizestep = id3->filesize / 256;
unsigned int cur_toc = id3->toc[percent];
unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256;
unsigned int plength = (next_toc - cur_toc) * toc_sizestep;
/* Seek to TOC mark */
pos = cur_toc * toc_sizestep;
/* Interpolate between this TOC mark and the next TOC mark */ /* Interpolate between this TOC mark and the next TOC mark */
int newtime_toc = newtime - percent * pct_timestep; int skipms_from_toc = newtime - percent * pct_timestep;
pos += (uint64_t)plength * newtime_toc / pct_timestep; if (skipms_from_toc < abs(skipms_from_curpos))
} else { {
unsigned int toc_sizestep = id3->filesize / 256;
unsigned int cur_toc = id3->toc[percent];
unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256;
unsigned int plength = (next_toc - cur_toc) * toc_sizestep;
pos = cur_toc * toc_sizestep + (uint64_t) plength * skipms_from_toc / pct_timestep;
}
} else if (newtime < abs(skipms_from_curpos)) {
/* No TOC exists, estimate the new position */ /* No TOC exists, estimate the new position */
pos = (uint64_t)newtime * id3->filesize / id3->length; pos = (uint64_t)newtime * id3->filesize / id3->length;
} }
// VBR seek might be very inaccurate in long files // VBR seek might be very inaccurate in long files
// So make sure that seeking actually happened in the intended direction // So make sure that seeking actually happened in the intended direction
// Fix jumps in the wrong direction by seeking relative to the current position // Fix jumps in the wrong direction by seeking relative to the current position
long delta = id3->elapsed - newtime; if (pos == -1 || (skipms_from_curpos >= 0 && pos > curpos) || (skipms_from_curpos < 0 && pos < curpos))
if ((delta >= 0 && pos > ci->curpos) || (delta < 0 && pos < ci->curpos))
{ {
pos = ci->curpos - delta * id3->filesize / id3->length; pos = curpos - skipms_from_curpos * (id3->filesize / id3->length);
//LOGF("сurpos relative seek: %d, curpos: %d, newtime: %d", pos, curpos, newtime);
} }
} else if (id3->bitrate) { } else if (id3->bitrate) {
pos = newtime * (id3->bitrate / 8); pos = newtime * (id3->bitrate / 8);