summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroman.artiukhin <bahusdrive@gmail.com>2023-08-31 00:45:46 +0300
committerSolomon Peachy <pizza@shaftnet.org>2023-09-18 11:29:05 -0400
commit6acb6446e6e4e31e3df983dd566739e691a9e521 (patch)
tree22b6e921be359a651f081bf0c89bfba37579de12
parent3c9be11411c4abeefc0cf2233fbd2b421ffebe64 (diff)
downloadrockbox-6acb6446e6e4e31e3df983dd566739e691a9e521.tar.gz
rockbox-6acb6446e6e4e31e3df983dd566739e691a9e521.zip
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
-rw-r--r--lib/rbcodec/codecs/libm4a/demux.c78
-rw-r--r--lib/rbcodec/codecs/libm4a/m4a.h2
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 @@
29 * 29 *
30 */ 30 */
31 31
32//#define DEBUG
33
32#include <string.h> 34#include <string.h>
33#include <inttypes.h> 35#include <inttypes.h>
34#include <stdlib.h> 36#include <stdlib.h>
@@ -411,7 +413,6 @@ static bool read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
411 413
412static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len) 414static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len)
413{ 415{
414 unsigned int i;
415 uint32_t numentries; 416 uint32_t numentries;
416 size_t size_remaining = chunk_len - 8; 417 size_t size_remaining = chunk_len - 8;
417 418
@@ -423,43 +424,29 @@ static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len)
423 size_remaining -= 4; 424 size_remaining -= 4;
424 425
425 qtmovie->res->num_sample_to_chunks = numentries; 426 qtmovie->res->num_sample_to_chunks = numentries;
426 qtmovie->res->sample_to_chunk = malloc(numentries * sizeof(sample_to_chunk_t)); 427 qtmovie->res->sample_to_chunk_offset = stream_tell(qtmovie->stream);
427
428 if (!qtmovie->res->sample_to_chunk)
429 {
430 DEBUGF("stsc too large\n");
431 return false;
432 }
433
434 for (i = 0; i < numentries; i++)
435 {
436 qtmovie->res->sample_to_chunk[i].first_chunk =
437 stream_read_uint32(qtmovie->stream);
438 qtmovie->res->sample_to_chunk[i].num_samples =
439 stream_read_uint32(qtmovie->stream);
440 stream_read_uint32(qtmovie->stream);
441 size_remaining -= 12;
442 }
443
444 if (size_remaining) 428 if (size_remaining)
445 { 429 {
446 DEBUGF("ehm, size remianing?\n");
447 stream_skip(qtmovie->stream, size_remaining); 430 stream_skip(qtmovie->stream, size_remaining);
448 } 431 }
449 432
450 return true; 433 return true;
451} 434}
452 435
436static void stream_read_sample_to_chunk(stream_t *stream, uint32_t *first_chunk, uint32_t *num_samples)
437{
438 (*first_chunk) = stream_read_uint32(stream);
439 (*num_samples) = stream_read_uint32(stream);
440 stream_skip(stream, 4);
441}
442
453static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) 443static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len)
454{ 444{
455 uint32_t i, k, old_i; 445 uint32_t i, k, old_i;
456 uint32_t numentries; 446 uint32_t numentries;
457 uint32_t idx = 0;
458 uint32_t frame; 447 uint32_t frame;
459 uint32_t offset; 448 uint32_t old_first, new_first;
460 uint32_t old_first; 449 uint32_t old_frame, new_frame;
461 uint32_t new_first;
462 uint32_t old_frame;
463 size_t size_remaining = chunk_len - 8; 450 size_t size_remaining = chunk_len - 8;
464 451
465 /* version + flags */ 452 /* version + flags */
@@ -494,10 +481,6 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len)
494 return false; 481 return false;
495 } 482 }
496 483
497 /* read first offset */
498 offset = stream_read_uint32(qtmovie->stream);
499 size_remaining -= 4;
500
501 /* Build up lookup table. The lookup table contains the sample index and 484 /* Build up lookup table. The lookup table contains the sample index and
502 * byte position in the file for each chunk. This table is used to seek 485 * byte position in the file for each chunk. This table is used to seek
503 * and resume (see m4a_seek() and m4a_seek_raw() in libm4a/m4a.c) and 486 * 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)
509 * accepted to be able to avoid allocation of the large sample_byte_size[] 492 * accepted to be able to avoid allocation of the large sample_byte_size[]
510 * table. This reduces the memory consumption by a factor of 2 or even 493 * table. This reduces the memory consumption by a factor of 2 or even
511 * more. */ 494 * more. */
495 uint32_t idx = 0;
496 for (i = 0; i < numentries; ++i)
497 {
498 if (i % accuracy_divider == 0)
499 {
500 qtmovie->res->lookup_table[idx++].offset = stream_read_uint32(qtmovie->stream);
501 }
502 else
503 {
504 stream_skip(qtmovie->stream, 4);
505 }
506 size_remaining -= 4;
507 }
508
509 idx = 0;
512 i = 1; 510 i = 1;
513 old_i = 1; 511 old_i = 1;
514 frame = 0; 512 frame = 0;
515 old_first = qtmovie->res->sample_to_chunk[0].first_chunk; 513
516 old_frame = qtmovie->res->sample_to_chunk[0].num_samples; 514 int32_t current_offset = stream_tell(qtmovie->stream);
517 new_first = qtmovie->res->sample_to_chunk[1].first_chunk; 515 stream_seek(qtmovie->stream, qtmovie->res->sample_to_chunk_offset);
516 stream_read_sample_to_chunk(qtmovie->stream, &old_first, &old_frame);
517 stream_read_sample_to_chunk(qtmovie->stream, &new_first, &new_frame);
518 for (k = 1; k < numentries; ++k) 518 for (k = 1; k < numentries; ++k)
519 { 519 {
520 for (; i < qtmovie->res->num_sample_to_chunks; ++i) 520 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)
522 if (i > old_i) 522 if (i > old_i)
523 { 523 {
524 /* Only access sample_to_chunk[] if new data is required. */ 524 /* Only access sample_to_chunk[] if new data is required. */
525 old_first = qtmovie->res->sample_to_chunk[i-1].first_chunk; 525 old_first = new_first;
526 old_frame = qtmovie->res->sample_to_chunk[i-1].num_samples; 526 old_frame = new_frame;
527 new_first = qtmovie->res->sample_to_chunk[i ].first_chunk; 527 stream_read_sample_to_chunk(qtmovie->stream, &new_first, &new_frame);
528 old_i = i; 528 old_i = i;
529 } 529 }
530 530
@@ -537,20 +537,16 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len)
537 537
538 if ((k-1) % accuracy_divider == 0) 538 if ((k-1) % accuracy_divider == 0)
539 { 539 {
540 qtmovie->res->lookup_table[idx].sample = frame; 540 qtmovie->res->lookup_table[idx++].sample = frame;
541 qtmovie->res->lookup_table[idx].offset = offset;
542 idx++;
543 } 541 }
544 542
545 frame -= (k - old_first) * old_frame; 543 frame -= (k - old_first) * old_frame;
546
547 offset = stream_read_uint32(qtmovie->stream);
548 size_remaining -= 4;
549 } 544 }
550 /* zero-terminate the lookup table */ 545 /* zero-terminate the lookup table */
551 qtmovie->res->lookup_table[idx].sample = 0; 546 qtmovie->res->lookup_table[idx].sample = 0;
552 qtmovie->res->lookup_table[idx].offset = 0; 547 qtmovie->res->lookup_table[idx].offset = 0;
553 548
549 stream_seek(qtmovie->stream, current_offset);
554 if (size_remaining) 550 if (size_remaining)
555 { 551 {
556 DEBUGF("ehm, size remianing?\n"); 552 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
71 fourcc_t format; 71 fourcc_t format;
72 void *buf; 72 void *buf;
73 73
74 sample_to_chunk_t *sample_to_chunk; 74 int32_t sample_to_chunk_offset;
75 uint32_t num_sample_to_chunks; 75 uint32_t num_sample_to_chunks;
76 76
77 sample_offset_t *lookup_table; 77 sample_offset_t *lookup_table;