From 6acb6446e6e4e31e3df983dd566739e691a9e521 Mon Sep 17 00:00:00 2001 From: "roman.artiukhin" Date: Thu, 31 Aug 2023 00:45:46 +0300 Subject: Codecs: mp4: Improve support for long files. Part 2 Don't store sample_to_chunk table and read data on demand instead (it's required only once for building lookup table). It allows to store 2x bigger lookup table. Change-Id: Ida79d0c281040300d6561e124fe10ebacb0e4679 --- lib/rbcodec/codecs/libm4a/demux.c | 78 +++++++++++++++++++-------------------- lib/rbcodec/codecs/libm4a/m4a.h | 2 +- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/lib/rbcodec/codecs/libm4a/demux.c b/lib/rbcodec/codecs/libm4a/demux.c index cd1b6c6077..27ecc162c6 100644 --- a/lib/rbcodec/codecs/libm4a/demux.c +++ b/lib/rbcodec/codecs/libm4a/demux.c @@ -29,6 +29,8 @@ * */ +//#define DEBUG + #include #include #include @@ -411,7 +413,6 @@ static bool read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len) static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len) { - unsigned int i; uint32_t numentries; size_t size_remaining = chunk_len - 8; @@ -423,43 +424,29 @@ static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len) size_remaining -= 4; qtmovie->res->num_sample_to_chunks = numentries; - qtmovie->res->sample_to_chunk = malloc(numentries * sizeof(sample_to_chunk_t)); - - if (!qtmovie->res->sample_to_chunk) - { - DEBUGF("stsc too large\n"); - return false; - } - - for (i = 0; i < numentries; i++) - { - qtmovie->res->sample_to_chunk[i].first_chunk = - stream_read_uint32(qtmovie->stream); - qtmovie->res->sample_to_chunk[i].num_samples = - stream_read_uint32(qtmovie->stream); - stream_read_uint32(qtmovie->stream); - size_remaining -= 12; - } - + qtmovie->res->sample_to_chunk_offset = stream_tell(qtmovie->stream); if (size_remaining) { - DEBUGF("ehm, size remianing?\n"); stream_skip(qtmovie->stream, size_remaining); } return true; } +static void stream_read_sample_to_chunk(stream_t *stream, uint32_t *first_chunk, uint32_t *num_samples) +{ + (*first_chunk) = stream_read_uint32(stream); + (*num_samples) = stream_read_uint32(stream); + stream_skip(stream, 4); +} + static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) { uint32_t i, k, old_i; uint32_t numentries; - uint32_t idx = 0; uint32_t frame; - uint32_t offset; - uint32_t old_first; - uint32_t new_first; - uint32_t old_frame; + uint32_t old_first, new_first; + uint32_t old_frame, new_frame; size_t size_remaining = chunk_len - 8; /* version + flags */ @@ -494,10 +481,6 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) return false; } - /* read first offset */ - offset = stream_read_uint32(qtmovie->stream); - size_remaining -= 4; - /* 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 @@ -509,12 +492,29 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) * accepted to be able to avoid allocation of the large sample_byte_size[] * table. This reduces the memory consumption by a factor of 2 or even * more. */ + uint32_t idx = 0; + for (i = 0; i < numentries; ++i) + { + if (i % accuracy_divider == 0) + { + qtmovie->res->lookup_table[idx++].offset = stream_read_uint32(qtmovie->stream); + } + else + { + stream_skip(qtmovie->stream, 4); + } + size_remaining -= 4; + } + + idx = 0; i = 1; old_i = 1; frame = 0; - old_first = qtmovie->res->sample_to_chunk[0].first_chunk; - old_frame = qtmovie->res->sample_to_chunk[0].num_samples; - new_first = qtmovie->res->sample_to_chunk[1].first_chunk; + + int32_t current_offset = stream_tell(qtmovie->stream); + stream_seek(qtmovie->stream, qtmovie->res->sample_to_chunk_offset); + stream_read_sample_to_chunk(qtmovie->stream, &old_first, &old_frame); + stream_read_sample_to_chunk(qtmovie->stream, &new_first, &new_frame); for (k = 1; k < numentries; ++k) { for (; i < qtmovie->res->num_sample_to_chunks; ++i) @@ -522,9 +522,9 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) if (i > old_i) { /* Only access sample_to_chunk[] if new data is required. */ - old_first = qtmovie->res->sample_to_chunk[i-1].first_chunk; - old_frame = qtmovie->res->sample_to_chunk[i-1].num_samples; - new_first = qtmovie->res->sample_to_chunk[i ].first_chunk; + old_first = new_first; + old_frame = new_frame; + stream_read_sample_to_chunk(qtmovie->stream, &new_first, &new_frame); old_i = i; } @@ -537,20 +537,16 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) if ((k-1) % accuracy_divider == 0) { - qtmovie->res->lookup_table[idx].sample = frame; - qtmovie->res->lookup_table[idx].offset = offset; - idx++; + qtmovie->res->lookup_table[idx++].sample = frame; } frame -= (k - old_first) * old_frame; - - offset = stream_read_uint32(qtmovie->stream); - size_remaining -= 4; } /* zero-terminate the lookup table */ qtmovie->res->lookup_table[idx].sample = 0; qtmovie->res->lookup_table[idx].offset = 0; + stream_seek(qtmovie->stream, current_offset); if (size_remaining) { DEBUGF("ehm, size remianing?\n"); diff --git a/lib/rbcodec/codecs/libm4a/m4a.h b/lib/rbcodec/codecs/libm4a/m4a.h index 9e159fe527..475773834c 100644 --- a/lib/rbcodec/codecs/libm4a/m4a.h +++ b/lib/rbcodec/codecs/libm4a/m4a.h @@ -71,7 +71,7 @@ typedef struct fourcc_t format; void *buf; - sample_to_chunk_t *sample_to_chunk; + int32_t sample_to_chunk_offset; uint32_t num_sample_to_chunks; sample_offset_t *lookup_table; -- cgit v1.2.3