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:
parent
49910eca4b
commit
1122cae028
1 changed files with 16 additions and 13 deletions
|
@ -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;
|
||||||
|
|
||||||
|
/* Interpolate between this TOC mark and the next TOC mark */
|
||||||
|
int skipms_from_toc = newtime - percent * pct_timestep;
|
||||||
|
if (skipms_from_toc < abs(skipms_from_curpos))
|
||||||
|
{
|
||||||
unsigned int toc_sizestep = id3->filesize / 256;
|
unsigned int toc_sizestep = id3->filesize / 256;
|
||||||
unsigned int cur_toc = id3->toc[percent];
|
unsigned int cur_toc = id3->toc[percent];
|
||||||
unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256;
|
unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256;
|
||||||
unsigned int plength = (next_toc - cur_toc) * toc_sizestep;
|
unsigned int plength = (next_toc - cur_toc) * toc_sizestep;
|
||||||
|
|
||||||
/* Seek to TOC mark */
|
pos = cur_toc * toc_sizestep + (uint64_t) plength * skipms_from_toc / pct_timestep;
|
||||||
pos = cur_toc * toc_sizestep;
|
}
|
||||||
|
} else if (newtime < abs(skipms_from_curpos)) {
|
||||||
/* Interpolate between this TOC mark and the next TOC mark */
|
|
||||||
int newtime_toc = newtime - percent * pct_timestep;
|
|
||||||
pos += (uint64_t)plength * newtime_toc / pct_timestep;
|
|
||||||
} else {
|
|
||||||
/* 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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue