summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Artiukhin <bahusdrive@gmail.com>2024-01-24 11:40:51 +0200
committerRoman Artiukhin <bahusdrive@gmail.com>2024-01-24 12:35:07 +0200
commit1122cae02804bd97887d51be6e5eee6a1616a09b (patch)
treee47a623ed7cc6c1b5a6df245b61adc4ae261fad2
parent49910eca4b400c817d1a6b65a53348280374927a (diff)
downloadrockbox-1122cae02804bd97887d51be6e5eee6a1616a09b.tar.gz
rockbox-1122cae02804bd97887d51be6e5eee6a1616a09b.zip
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
-rw-r--r--lib/rbcodec/codecs/mpa.c29
1 files 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)
176 struct mp3entry *id3 = ci->id3; 176 struct mp3entry *id3 = ci->id3;
177 177
178 if (id3->vbr) { 178 if (id3->vbr) {
179 int curpos = ci->curpos - id3->first_frame_offset;
180 long skipms_from_curpos = curpos > 0 ? (long) (id3->elapsed - newtime) : - newtime;
179 if (id3->has_toc) { 181 if (id3->has_toc) {
180 /* Use the TOC to find the new position */ 182 /* Use the TOC to find the new position */
181 unsigned int percent = ((uint64_t)newtime * 100) / id3->length; 183 unsigned int percent = ((uint64_t)newtime * 100) / id3->length;
@@ -183,28 +185,29 @@ static int get_file_pos(int newtime)
183 percent = 99; 185 percent = 99;
184 186
185 unsigned int pct_timestep = id3->length / 100; 187 unsigned int pct_timestep = id3->length / 100;
186 unsigned int toc_sizestep = id3->filesize / 256;
187 unsigned int cur_toc = id3->toc[percent];
188 unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256;
189 unsigned int plength = (next_toc - cur_toc) * toc_sizestep;
190
191 /* Seek to TOC mark */
192 pos = cur_toc * toc_sizestep;
193 188
194 /* Interpolate between this TOC mark and the next TOC mark */ 189 /* Interpolate between this TOC mark and the next TOC mark */
195 int newtime_toc = newtime - percent * pct_timestep; 190 int skipms_from_toc = newtime - percent * pct_timestep;
196 pos += (uint64_t)plength * newtime_toc / pct_timestep; 191 if (skipms_from_toc < abs(skipms_from_curpos))
197 } else { 192 {
193 unsigned int toc_sizestep = id3->filesize / 256;
194 unsigned int cur_toc = id3->toc[percent];
195 unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256;
196 unsigned int plength = (next_toc - cur_toc) * toc_sizestep;
197
198 pos = cur_toc * toc_sizestep + (uint64_t) plength * skipms_from_toc / pct_timestep;
199 }
200 } else if (newtime < abs(skipms_from_curpos)) {
198 /* No TOC exists, estimate the new position */ 201 /* No TOC exists, estimate the new position */
199 pos = (uint64_t)newtime * id3->filesize / id3->length; 202 pos = (uint64_t)newtime * id3->filesize / id3->length;
200 } 203 }
201 // VBR seek might be very inaccurate in long files 204 // VBR seek might be very inaccurate in long files
202 // So make sure that seeking actually happened in the intended direction 205 // So make sure that seeking actually happened in the intended direction
203 // Fix jumps in the wrong direction by seeking relative to the current position 206 // Fix jumps in the wrong direction by seeking relative to the current position
204 long delta = id3->elapsed - newtime; 207 if (pos == -1 || (skipms_from_curpos >= 0 && pos > curpos) || (skipms_from_curpos < 0 && pos < curpos))
205 if ((delta >= 0 && pos > ci->curpos) || (delta < 0 && pos < ci->curpos))
206 { 208 {
207 pos = ci->curpos - delta * id3->filesize / id3->length; 209 pos = curpos - skipms_from_curpos * (id3->filesize / id3->length);
210 //LOGF("сurpos relative seek: %d, curpos: %d, newtime: %d", pos, curpos, newtime);
208 } 211 }
209 } else if (id3->bitrate) { 212 } else if (id3->bitrate) {
210 pos = newtime * (id3->bitrate / 8); 213 pos = newtime * (id3->bitrate / 8);