diff options
author | roman.artiukhin <bahusdrive@gmail.com> | 2023-08-31 00:45:46 +0300 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2023-09-18 11:29:05 -0400 |
commit | 6acb6446e6e4e31e3df983dd566739e691a9e521 (patch) | |
tree | 22b6e921be359a651f081bf0c89bfba37579de12 /lib/rbcodec/codecs/libm4a | |
parent | 3c9be11411c4abeefc0cf2233fbd2b421ffebe64 (diff) | |
download | rockbox-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
Diffstat (limited to 'lib/rbcodec/codecs/libm4a')
-rw-r--r-- | lib/rbcodec/codecs/libm4a/demux.c | 78 | ||||
-rw-r--r-- | 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 @@ | |||
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 | ||
412 | static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len) | 414 | static 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 | ||
436 | static 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 | |||
453 | static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) | 443 | static 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; |