Index: apps/codecs/libfaad/bits.c =================================================================== --- apps/codecs/libfaad/bits.c (revision 29730) +++ apps/codecs/libfaad/bits.c (working copy) @@ -48,7 +48,7 @@ memset(ld, 0, sizeof(bitfile)); - if (buffer_size == 0 || _buffer == NULL || (buffer_size+12)>BUFFER_SIZE) + if (buffer_size == 0 || _buffer == NULL || buffer_size>BUFFER_SIZE) { ld->error = 1; ld->no_more_reading = 1; @@ -56,7 +56,7 @@ } ld->buffer = &static_buffer; - memset(ld->buffer, 0, (buffer_size+12)*sizeof(uint8_t)); + memset(ld->buffer, 0, buffer_size*sizeof(uint8_t)); memcpy(ld->buffer, _buffer, buffer_size*sizeof(uint8_t)); ld->buffer_size = buffer_size; Index: apps/codecs/aac.c =================================================================== --- apps/codecs/aac.c (revision 29730) +++ apps/codecs/aac.c (working copy) @@ -27,6 +27,10 @@ CODEC_HEADER +/* The maximum buffer size handled by faad (see libfaad/bits.c). This amount + * of bytes is buffered for each frame. */ +#define FAAD_BYTE_BUFFER_SIZE 2048 + /* Global buffers to be used in the mdct synthesis. This way the arrays can * be moved to IRAM for some targets */ #define GB_BUF_SIZE 1024 @@ -175,7 +179,11 @@ { lead_trim = ci->id3->lead_trim; } - + /* + printf("num_sample_to_chunks = %d\n", demux_res.num_sample_to_chunks); + printf("num_lookup_table = %d\n", demux_res.num_lookup_table); + printf("num_time_to_samples = %d\n", demux_res.num_time_to_samples); + */ /* The main decoding loop */ while (i < demux_res.num_sample_byte_sizes) { ci->yield(); @@ -211,7 +219,7 @@ * that an good question (but files with gaps do exist, so who * knows?), so we don't support that - for now, at least. */ - file_offset = get_sample_offset(&demux_res, i); + file_offset = check_sample_offset(&demux_res, i); if (file_offset > ci->curpos) { @@ -225,7 +233,7 @@ } /* Request the required number of bytes from the input buffer */ - buffer=ci->request_buffer(&n, demux_res.sample_byte_size[i]); + buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE); /* Decode one block - returned samples will be host-endian */ ret = NeAACDecDecode(decoder, &frame_info, buffer, n); Index: apps/codecs/alac.c =================================================================== --- apps/codecs/alac.c (revision 29730) +++ apps/codecs/alac.c (working copy) @@ -25,6 +25,10 @@ CODEC_HEADER +/* The maximum buffer size handled. This amount of bytes is buffered for each + * frame. */ +#define ALAC_BYTE_BUFFER_SIZE 32768 + static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR; /* this is the codec entry point */ @@ -111,8 +115,8 @@ } /* Request the required number of bytes from the input buffer */ - buffer=ci->request_buffer(&n, demux_res.sample_byte_size[i]); - if (n!=demux_res.sample_byte_size[i]) { + buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); + if (n!=ALAC_BYTE_BUFFER_SIZE) { retval = CODEC_ERROR; goto done; } Index: apps/codecs/libm4a/m4a.c =================================================================== --- apps/codecs/libm4a/m4a.c (revision 29730) +++ apps/codecs/libm4a/m4a.c (working copy) @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2005 Dave Chapman + * Copyright (C) 2005 Dave Chapman, 2011 Andree Buschmann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -122,147 +122,44 @@ stream->eof=0; } -/* This function was part of the original alac decoder implementation */ - -int get_sample_info(demux_res_t *demux_res, uint32_t samplenum, - uint32_t *sample_duration, - uint32_t *sample_byte_size) +/* Check if there is a dedicated byte position contained for the given frame. + * Return this byte position in case of success or return -1. */ +int check_sample_offset(demux_res_t *demux_res, uint32_t frame) { - unsigned int duration_index_accum = 0; - unsigned int duration_cur_index = 0; - - if (samplenum >= demux_res->num_sample_byte_sizes) { - return 0; + uint32_t i = 0; + for (i=0; inum_lookup_table; ++i) + { + if (demux_res->lookup_table[i].sample > frame || + demux_res->lookup_table[i].offset == 0) + return -1; + if (demux_res->lookup_table[i].sample == frame) + break; } - - if (!demux_res->num_time_to_samples) { - return 0; - } - - while ((demux_res->time_to_sample[duration_cur_index].sample_count - + duration_index_accum) <= samplenum) { - duration_index_accum += - demux_res->time_to_sample[duration_cur_index].sample_count; - - duration_cur_index++; - if (duration_cur_index >= demux_res->num_time_to_samples) { - return 0; - } - } - - *sample_duration = - demux_res->time_to_sample[duration_cur_index].sample_duration; - *sample_byte_size = demux_res->sample_byte_size[samplenum]; - - return 1; + return demux_res->lookup_table[i].offset; } -unsigned int get_sample_offset(demux_res_t *demux_res, uint32_t sample) +/* Find the exact or preceding frame in lookup_table[]. Return both frame + * and byte position of this match. */ +static void gather_offset(demux_res_t *demux_res, uint32_t *frame, uint32_t *offset) { - uint32_t chunk = 1; - uint32_t range_samples = 0; - uint32_t total_samples = 0; - uint32_t chunk_sample; - uint32_t prev_chunk; - uint32_t prev_chunk_samples; - uint32_t file_offset; - uint32_t i; - - /* First check we have the appropriate metadata - we should always - * have it. - */ - - if (sample >= demux_res->num_sample_byte_sizes || - !demux_res->num_sample_to_chunks || - !demux_res->num_chunk_offsets) + uint32_t i = 0; + for (i=0; inum_lookup_table; ++i) { - return 0; - } - - /* Locate the chunk containing the sample */ - - prev_chunk = demux_res->sample_to_chunk[0].first_chunk; - prev_chunk_samples = demux_res->sample_to_chunk[0].num_samples; - - for (i = 1; i < demux_res->num_sample_to_chunks; i++) - { - chunk = demux_res->sample_to_chunk[i].first_chunk; - range_samples = (chunk - prev_chunk) * prev_chunk_samples; - - if (sample < total_samples + range_samples) - { + if (demux_res->lookup_table[i].offset == 0) break; - } - - total_samples += range_samples; - prev_chunk = demux_res->sample_to_chunk[i].first_chunk; - prev_chunk_samples = demux_res->sample_to_chunk[i].num_samples; + if (demux_res->lookup_table[i].sample > *frame) + break; } - - if (prev_chunk_samples > 0 && - sample >= demux_res->sample_to_chunk[0].num_samples) - { - chunk = prev_chunk + (sample - total_samples) / prev_chunk_samples; - } - else - { - chunk = 1; - } - - /* Get sample of the first sample in the chunk */ - - chunk_sample = total_samples + (chunk - prev_chunk) * prev_chunk_samples; - - /* Get offset in file */ - - if (chunk > demux_res->num_chunk_offsets) - { - file_offset = demux_res->chunk_offset[demux_res->num_chunk_offsets - 1]; - } - else - { - file_offset = demux_res->chunk_offset[chunk - 1]; - } - - if (chunk_sample > sample) - { - return 0; - } - - for (i = chunk_sample; i < sample; i++) - { - file_offset += demux_res->sample_byte_size[i]; - } - - if (file_offset > demux_res->mdat_offset + demux_res->mdat_len) - { - return 0; - } - - return file_offset; + i = (i>0) ? i-1 : 0; /* We want the last chunk _before_ *frame. */ + *frame = demux_res->lookup_table[i].sample; + *offset = demux_res->lookup_table[i].offset; } -/* Seek to the sample containing sound_sample_loc. Return 1 on success - * (and modify sound_samples_done and current_sample), 0 if failed. +/* Seek to desired sound sample location. Return 1 on success (and modify + * sound_samples_done and current_sample), 0 if failed. * - * Seeking uses the following arrays: - * - * 1) the time_to_sample array contains the duration (in sound samples) - * of each sample of data. - * - * 2) the sample_byte_size array contains the length in bytes of each - * sample. - * - * 3) the sample_to_chunk array contains information about which chunk - * of samples each sample belongs to. - * - * 4) the chunk_offset array contains the file offset of each chunk. - * - * So find the sample number we are going to seek to (using time_to_sample) - * and then find the offset in the file (using sample_to_chunk, - * chunk_offset sample_byte_size, in that order.). - * - */ + * Find the sample (=frame) that contains the given sound sample, find a best + * fit for this sample in the lookup_table[], seek to the byte position. */ unsigned int alac_seek(demux_res_t* demux_res, stream_t* stream, uint32_t sound_sample_loc, uint32_t* sound_samples_done, int* current_sample) @@ -300,8 +197,8 @@ ++i; } - /* We know the new block, now calculate the file position. */ - new_pos = get_sample_offset(demux_res, new_sample); + /* We know the new sample (=frame), now calculate the file position. */ + gather_offset(demux_res, &new_sample, &new_pos); /* We know the new file position, so let's try to seek to it */ if (stream->ci->seek_buffer(new_pos)) @@ -319,72 +216,38 @@ * * Seeking uses the following arrays: * - * 1) the chunk_offset array contains the file offset of each chunk. + * 1) the lookup_table array contains the file offset for the first sample + * of each chunk. * - * 2) the sample_to_chunk array contains information about which chunk - * of samples each sample belongs to. - * - * 3) the sample_byte_size array contains the length in bytes of each - * sample. - * - * 4) the time_to_sample array contains the duration (in sound samples) + * 2) the time_to_sample array contains the duration (in sound samples) * of each sample of data. * - * Locate the chunk containing location (using chunk_offset), find the - * sample of that chunk (using sample_to_chunk) and finally the location - * of that sample (using sample_byte_size). Then use time_to_sample to + * Locate the chunk containing location (using lookup_table), find the first + * sample of that chunk (using lookup_table). Then use time_to_sample to * calculate the sound_samples_done value. */ unsigned int alac_seek_raw(demux_res_t* demux_res, stream_t* stream, uint32_t file_loc, uint32_t* sound_samples_done, int* current_sample) { - uint32_t chunk_sample = 0; /* Holds the chunk/frame index. */ - uint32_t total_samples = 0; /* Sums up total amount of chunks/frames. */ - uint32_t new_sound_sample = 0; /* Sums up total amount of samples. */ + uint32_t i; + uint32_t chunk_sample = 0; + uint32_t total_samples = 0; + uint32_t new_sound_sample = 0; + uint32_t tmp_dur; + uint32_t tmp_cnt; uint32_t new_pos; - uint32_t chunk; - uint32_t i, tmp_dur, tmp_cnt; - /* There is no metadata available to perform raw seek. */ - if (!demux_res->num_chunk_offsets || !demux_res->num_sample_to_chunks) + /* Gather sample index. */ + for (i=0; i < demux_res->num_lookup_table; ++i) { - return 0; - } - - /* Locate the chunk containing file_loc. */ - chunk = 0; - while (chunk < demux_res->num_chunk_offsets) - { - if (file_loc < demux_res->chunk_offset[chunk]) - { + if (demux_res->lookup_table[i].offset > file_loc) break; - } - ++chunk; } - new_pos = demux_res->chunk_offset[chunk > 0 ? chunk - 1 : 0]; - - /* Get the first sample of the chunk. */ - i = 1; - sample_to_chunk_t *tab1 = demux_res->sample_to_chunk; - while (i < demux_res->num_sample_to_chunks) - { - if (chunk <= tab1[i].first_chunk) - { - break; - } - chunk_sample += tab1[i-1].num_samples * (tab1[i].first_chunk - tab1[i-1].first_chunk); - ++i; - } - chunk_sample += (chunk - tab1[i-1].first_chunk) * tab1[i-1].num_samples; + i = (i>0) ? i-1 : 0; /* We want the last chunk _before_ file_loc. */ + chunk_sample = demux_res->lookup_table[i].sample; + new_pos = demux_res->lookup_table[i].offset; - /* Get the position within the chunk. */ - while (chunk_sample < demux_res->num_sample_byte_sizes && - file_loc >= new_pos + demux_res->sample_byte_size[chunk_sample]) - { - new_pos += demux_res->sample_byte_size[chunk_sample++]; - } - /* Get sound sample offset. */ i = 0; time_to_sample_t *tab2 = demux_res->time_to_sample; Index: apps/codecs/libm4a/demux.c =================================================================== --- apps/codecs/libm4a/demux.c (revision 29730) +++ apps/codecs/libm4a/demux.c (working copy) @@ -354,8 +354,6 @@ static bool read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len) { - unsigned int i; - uint32_t numentries; size_t size_remaining = chunk_len - 8; /* version */ @@ -377,35 +375,11 @@ } size_remaining -= 4; - numentries = stream_read_uint32(qtmovie->stream); + qtmovie->res->num_sample_byte_sizes = stream_read_uint32(qtmovie->stream); size_remaining -= 4; - qtmovie->res->num_sample_byte_sizes = numentries; - qtmovie->res->sample_byte_size = malloc(numentries * sizeof(*qtmovie->res->sample_byte_size)); - - if (!qtmovie->res->sample_byte_size) - { - DEBUGF("stsz too large\n"); - return false; - } - - for (i = 0; i < numentries; i++) - { - uint32_t v = stream_read_uint32(qtmovie->stream); - - if (v > 0x0000ffff) - { - DEBUGF("stsz[%d] > 65 kB (%ld)\n", i, (long)v); - return false; - } - - qtmovie->res->sample_byte_size[i] = v; - size_remaining -= 4; - } - if (size_remaining) { - DEBUGF("ehm, size remianing?\n"); stream_skip(qtmovie->stream, size_remaining); } @@ -426,8 +400,7 @@ size_remaining -= 4; qtmovie->res->num_sample_to_chunks = numentries; - qtmovie->res->sample_to_chunk = malloc(numentries * - sizeof(*qtmovie->res->sample_to_chunk)); + qtmovie->res->sample_to_chunk = malloc(numentries * sizeof(sample_to_chunk_t)); if (!qtmovie->res->sample_to_chunk) { @@ -456,8 +429,14 @@ static bool read_chunk_stco(qtmovie_t *qtmovie, size_t chunk_len) { - unsigned int i; + uint32_t i, k; uint32_t numentries; + int32_t idx = 0; + int32_t frame; + int32_t offset; + int32_t old_first; + int32_t new_first; + int32_t old_frame; size_t size_remaining = chunk_len - 8; /* version + flags */ @@ -466,20 +445,48 @@ numentries = stream_read_uint32(qtmovie->stream); size_remaining -= 4; + + qtmovie->res->num_lookup_table = numentries; + qtmovie->res->lookup_table = malloc(numentries * sizeof(*qtmovie->res->lookup_table)); - qtmovie->res->num_chunk_offsets = numentries; - qtmovie->res->chunk_offset = malloc(numentries * - sizeof(*qtmovie->res->chunk_offset)); - - if (!qtmovie->res->chunk_offset) + if (!qtmovie->res->lookup_table) { - DEBUGF("stco too large\n"); + DEBUGF("stco too large to allocate lookup_table[]\n"); return false; } - for (i = 0; i < numentries; i++) + /* 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. */ + i = 1; + frame = 0; + old_frame = qtmovie->res->sample_to_chunk[0].num_samples; + old_first = qtmovie->res->sample_to_chunk[0].first_chunk; + for (k = 1; k < numentries; ++k) { - qtmovie->res->chunk_offset[i] = stream_read_uint32(qtmovie->stream); + for (; i < qtmovie->res->num_sample_to_chunks; ++i) + { + old_frame = qtmovie->res->sample_to_chunk[i-1].num_samples; + old_first = qtmovie->res->sample_to_chunk[i-1].first_chunk; + new_first = qtmovie->res->sample_to_chunk[i ].first_chunk; + + if (qtmovie->res->sample_to_chunk[i].first_chunk > k) + break; + + frame += (new_first - old_first) * old_frame; + } + frame += (k - old_first) * old_frame; + + qtmovie->res->lookup_table[idx].sample = frame; + qtmovie->res->lookup_table[idx].offset = offset; + idx++; + + frame -= (k - old_first) * old_frame; + + offset = stream_read_uint32(qtmovie->stream); size_remaining -= 4; } Index: apps/codecs/libm4a/m4a.h =================================================================== --- apps/codecs/libm4a/m4a.h (revision 29730) +++ apps/codecs/libm4a/m4a.h (working copy) @@ -59,6 +59,12 @@ typedef struct { + uint32_t sample; + uint32_t offset; +} sample_offset_t; + +typedef struct +{ uint16_t num_channels; uint16_t sound_sample_size; uint32_t sound_sample_rate; @@ -68,13 +74,12 @@ sample_to_chunk_t *sample_to_chunk; uint32_t num_sample_to_chunks; - uint32_t *chunk_offset; - uint32_t num_chunk_offsets; + sample_offset_t *lookup_table; + uint32_t num_lookup_table; time_to_sample_t *time_to_sample; uint32_t num_time_to_samples; - uint16_t *sample_byte_size; uint32_t num_sample_byte_sizes; uint32_t codecdata_len; @@ -132,5 +137,6 @@ int* current_sample); unsigned int alac_seek_raw (demux_res_t* demux_res, stream_t* stream, uint32_t file_loc, uint32_t* sound_samples_done, int* current_sample); +int check_sample_offset(demux_res_t *demux_res, uint32_t frame); #endif /* STREAM_H */