summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroman.artiukhin <bahusdrive@gmail.com>2023-09-05 00:45:32 +0300
committerroman.artiukhin <bahusdrive@gmail.com>2023-09-20 11:43:39 +0300
commit57409f52d5da3665a91c6cf2cbcef86ea1004ccf (patch)
tree7de9c0af2c15a7a6b5d6b36493e545b658d8a5cc
parente01055a287500d8cc90cda3b4816d3dc2f07bde4 (diff)
downloadrockbox-57409f52d5.tar.gz
rockbox-57409f52d5.zip
Codecs: mp4: Accurate seek in large files with small lookup_table
Read sample_byte_sizes table on demand when it can't be cached Change-Id: I2191be63ceebfd8b16e1e973e13c5b51986b6564
-rw-r--r--lib/rbcodec/codecs/libm4a/demux.c11
-rw-r--r--lib/rbcodec/codecs/libm4a/m4a.c19
-rw-r--r--lib/rbcodec/codecs/libm4a/m4a.h1
3 files changed, 25 insertions, 6 deletions
diff --git a/lib/rbcodec/codecs/libm4a/demux.c b/lib/rbcodec/codecs/libm4a/demux.c
index 25462db030..8a424c5187 100644
--- a/lib/rbcodec/codecs/libm4a/demux.c
+++ b/lib/rbcodec/codecs/libm4a/demux.c
@@ -400,7 +400,8 @@ static bool read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
}
else
{
- DEBUGF("stsz too large, ignoring it\n");
+ qtmovie->res->sample_byte_sizes_offset = stream_tell(qtmovie->stream);
+ DEBUGF("stsz too large: %u, save sample_byte_sizes_offset\n", numsizes);
}
if (size_remaining)
@@ -481,6 +482,14 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len)
return false;
}
+ // Reading sample_byte_sizes data on seek can lead to additional re-buffering.
+ // So skip it if we have good enough seek accuracy via lookup_table (3000 ms)
+ if (qtmovie->res->sample_byte_sizes_offset && ci->id3->length / fit_numentries <= 3000)
+ {
+ qtmovie->res->sample_byte_sizes_offset = 0;
+ DEBUGF("lookup_table seek accuracy %ld ms, ignoring sample_byte_sizes_offset \n", ci->id3->length / fit_numentries);
+ }
+
/* Build up lookup table. The lookup table contains the sample index and
* byte position in the file for each chunk. This table is used to seek
* and resume (see m4a_seek() and m4a_seek_raw() in libm4a/m4a.c) and
diff --git a/lib/rbcodec/codecs/libm4a/m4a.c b/lib/rbcodec/codecs/libm4a/m4a.c
index 295c39c5ff..b63b8bad2c 100644
--- a/lib/rbcodec/codecs/libm4a/m4a.c
+++ b/lib/rbcodec/codecs/libm4a/m4a.c
@@ -211,11 +211,13 @@ unsigned int m4a_seek(demux_res_t* demux_res, stream_t* stream,
sound_sample_i += time_cnt * time_dur;
}
- DEBUGF("seek chunk=%lu, sample=%lu, soundsample=%lu, offset=%lu\n",
- (unsigned long)chunk, (unsigned long)chunk_first_sample,
- sound_sample_i, (unsigned long)offset);
+ if (demux_res->sample_byte_sizes_offset)
+ {
+ stream->ci->seek_buffer(demux_res->sample_byte_sizes_offset + chunk_first_sample * 4);
+ }
- if (tsz_tab) {
+ if (tsz_tab || demux_res->sample_byte_sizes_offset)
+ {
/* We have a sample-to-bytes table available so we can do accurate
* seeking. Move one sample at a time and update the file offset and
* PCM sample offset as we go. */
@@ -229,7 +231,7 @@ unsigned int m4a_seek(demux_res_t* demux_res, stream_t* stream,
time_dur = tts_tab[time].sample_duration;
}
- offset += tsz_tab[i];
+ offset += tsz_tab ? tsz_tab[i] : stream_read_uint32(stream);
sound_sample_i += time_dur;
time_cnt--;
}
@@ -239,6 +241,13 @@ unsigned int m4a_seek(demux_res_t* demux_res, stream_t* stream,
sample_i = chunk_first_sample;
}
+ DEBUGF("seek chunk=%lu, chunk_first_sample=%lu, sample_i=%u, soundsample=%lu, offset=%lu\n",
+ (unsigned long)chunk,
+ (unsigned long)chunk_first_sample,
+ sample_i,
+ (unsigned long)sound_sample_i,
+ (unsigned long)offset);
+
if (stream->ci->seek_buffer(offset))
{
*sound_samples_done = sound_sample_i;
diff --git a/lib/rbcodec/codecs/libm4a/m4a.h b/lib/rbcodec/codecs/libm4a/m4a.h
index 7120f8b4c6..14b22f5dbf 100644
--- a/lib/rbcodec/codecs/libm4a/m4a.h
+++ b/lib/rbcodec/codecs/libm4a/m4a.h
@@ -82,6 +82,7 @@ typedef struct
uint32_t *sample_byte_sizes;
uint32_t num_sample_byte_sizes;
+ int32_t sample_byte_sizes_offset;
uint32_t codecdata_len;
uint8_t codecdata[MAX_CODECDATA_SIZE];