From 1122cae02804bd97887d51be6e5eee6a1616a09b Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Wed, 24 Jan 2024 11:40:51 +0200 Subject: 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 --- lib/rbcodec/codecs/mpa.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/rbcodec/codecs/mpa.c b/lib/rbcodec/codecs/mpa.c index c5d47a6791..5fdcb38da8 100644 --- a/lib/rbcodec/codecs/mpa.c +++ b/lib/rbcodec/codecs/mpa.c @@ -176,6 +176,8 @@ static int get_file_pos(int newtime) struct mp3entry *id3 = ci->id3; 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) { /* Use the TOC to find the new position */ unsigned int percent = ((uint64_t)newtime * 100) / id3->length; @@ -183,28 +185,29 @@ static int get_file_pos(int newtime) percent = 99; 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 */ - int newtime_toc = newtime - percent * pct_timestep; - pos += (uint64_t)plength * newtime_toc / pct_timestep; - } else { + 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 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 */ pos = (uint64_t)newtime * id3->filesize / id3->length; } // VBR seek might be very inaccurate in long files // So make sure that seeking actually happened in the intended direction // Fix jumps in the wrong direction by seeking relative to the current position - long delta = id3->elapsed - newtime; - if ((delta >= 0 && pos > ci->curpos) || (delta < 0 && pos < ci->curpos)) + if (pos == -1 || (skipms_from_curpos >= 0 && pos > curpos) || (skipms_from_curpos < 0 && pos < 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) { pos = newtime * (id3->bitrate / 8); -- cgit v1.2.3