Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

roman.artiukhin and committed by
Solomon Peachy
6acb6446 3c9be114

+38 -42
+37 -41
lib/rbcodec/codecs/libm4a/demux.c
··· 29 29 * 30 30 */ 31 31 32 + //#define DEBUG 33 + 32 34 #include <string.h> 33 35 #include <inttypes.h> 34 36 #include <stdlib.h> ··· 411 413 412 414 static bool read_chunk_stsc(qtmovie_t *qtmovie, size_t chunk_len) 413 415 { 414 - unsigned int i; 415 416 uint32_t numentries; 416 417 size_t size_remaining = chunk_len - 8; 417 418 ··· 423 424 size_remaining -= 4; 424 425 425 426 qtmovie->res->num_sample_to_chunks = numentries; 426 - qtmovie->res->sample_to_chunk = malloc(numentries * sizeof(sample_to_chunk_t)); 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 - 427 + qtmovie->res->sample_to_chunk_offset = stream_tell(qtmovie->stream); 444 428 if (size_remaining) 445 429 { 446 - DEBUGF("ehm, size remianing?\n"); 447 430 stream_skip(qtmovie->stream, size_remaining); 448 431 } 449 432 450 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 443 static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) 454 444 { 455 445 uint32_t i, k, old_i; 456 446 uint32_t numentries; 457 - uint32_t idx = 0; 458 447 uint32_t frame; 459 - uint32_t offset; 460 - uint32_t old_first; 461 - uint32_t new_first; 462 - uint32_t old_frame; 448 + uint32_t old_first, new_first; 449 + uint32_t old_frame, new_frame; 463 450 size_t size_remaining = chunk_len - 8; 464 451 465 452 /* version + flags */ ··· 494 481 return false; 495 482 } 496 483 497 - /* read first offset */ 498 - offset = stream_read_uint32(qtmovie->stream); 499 - size_remaining -= 4; 500 - 501 484 /* Build up lookup table. The lookup table contains the sample index and 502 485 * byte position in the file for each chunk. This table is used to seek 503 486 * and resume (see m4a_seek() and m4a_seek_raw() in libm4a/m4a.c) and ··· 509 492 * accepted to be able to avoid allocation of the large sample_byte_size[] 510 493 * table. This reduces the memory consumption by a factor of 2 or even 511 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 510 i = 1; 513 511 old_i = 1; 514 512 frame = 0; 515 - old_first = qtmovie->res->sample_to_chunk[0].first_chunk; 516 - old_frame = qtmovie->res->sample_to_chunk[0].num_samples; 517 - new_first = qtmovie->res->sample_to_chunk[1].first_chunk; 513 + 514 + int32_t current_offset = stream_tell(qtmovie->stream); 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 518 for (k = 1; k < numentries; ++k) 519 519 { 520 520 for (; i < qtmovie->res->num_sample_to_chunks; ++i) ··· 522 522 if (i > old_i) 523 523 { 524 524 /* Only access sample_to_chunk[] if new data is required. */ 525 - old_first = qtmovie->res->sample_to_chunk[i-1].first_chunk; 526 - old_frame = qtmovie->res->sample_to_chunk[i-1].num_samples; 527 - new_first = qtmovie->res->sample_to_chunk[i ].first_chunk; 525 + old_first = new_first; 526 + old_frame = new_frame; 527 + stream_read_sample_to_chunk(qtmovie->stream, &new_first, &new_frame); 528 528 old_i = i; 529 529 } 530 530 ··· 537 537 538 538 if ((k-1) % accuracy_divider == 0) 539 539 { 540 - qtmovie->res->lookup_table[idx].sample = frame; 541 - qtmovie->res->lookup_table[idx].offset = offset; 542 - idx++; 540 + qtmovie->res->lookup_table[idx++].sample = frame; 543 541 } 544 542 545 543 frame -= (k - old_first) * old_frame; 546 - 547 - offset = stream_read_uint32(qtmovie->stream); 548 - size_remaining -= 4; 549 544 } 550 545 /* zero-terminate the lookup table */ 551 546 qtmovie->res->lookup_table[idx].sample = 0; 552 547 qtmovie->res->lookup_table[idx].offset = 0; 553 548 549 + stream_seek(qtmovie->stream, current_offset); 554 550 if (size_remaining) 555 551 { 556 552 DEBUGF("ehm, size remianing?\n");
+1 -1
lib/rbcodec/codecs/libm4a/m4a.h
··· 71 71 fourcc_t format; 72 72 void *buf; 73 73 74 - sample_to_chunk_t *sample_to_chunk; 74 + int32_t sample_to_chunk_offset; 75 75 uint32_t num_sample_to_chunks; 76 76 77 77 sample_offset_t *lookup_table;