Index: apps/codecs/aac.c =================================================================== --- apps/codecs/aac.c (revision 29714) +++ apps/codecs/aac.c (working copy) @@ -47,8 +47,7 @@ stream_t input_stream; uint32_t sound_samples_done; uint32_t elapsed_time; - uint32_t sample_duration; - uint32_t sample_byte_size; + int max_frame_size; int file_offset; int framelength; int lead_trim = 0; @@ -177,6 +176,15 @@ { lead_trim = ci->id3->lead_trim; } + + /************************** + * TEST BEGIN + *************************/ + get_max_sample_byte_size(&demux_res, &max_frame_size); + build_m4a_sync_tab(&demux_res); + /************************** + * TEST END + *************************/ /* The main decoding loop */ while (i < demux_res.num_sample_byte_sizes) { @@ -207,25 +215,13 @@ ci->seek_complete(); } - /* Lookup the length (in samples and bytes) of block i */ - if (!get_sample_info(&demux_res, i, &sample_duration, - &sample_byte_size)) { - LOGF("AAC: get_sample_info error\n"); - err = CODEC_ERROR; - goto done; - } - - /* There can be gaps between chunks, so skip ahead if needed. It - * doesn't seem to happen much, but it probably means that a - * "proper" file can have chunks out of order. Why one would want - * 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); + /* There can be gaps between chunks, so skip ahead if needed. */ + file_offset = get_m4a_sync_offset(i); - if (file_offset > ci->curpos) + int bytes_to_skip = file_offset - ci->curpos; + if (bytes_to_skip > 0) { - ci->advance_buffer(file_offset - ci->curpos); + ci->advance_buffer(bytes_to_skip); } else if (file_offset == 0) { @@ -235,7 +231,7 @@ } /* Request the required number of bytes from the input buffer */ - buffer=ci->request_buffer(&n,sample_byte_size); + buffer=ci->request_buffer(&n, max_frame_size); /* Decode one block - returned samples will be host-endian */ ret = NeAACDecDecode(decoder, &frame_info, buffer, n); @@ -248,34 +244,17 @@ } /* Advance codec buffer (no need to call set_offset because of this) */ - ci->advance_buffer(n); + ci->advance_buffer(frame_info.bytesconsumed); /* Output the audio */ ci->yield(); - /* Ensure correct sample_duration is used. For SBR upsampling files - * sample_duration is only half the size of real output frame size. */ - sample_duration *= sbr_fac; - + /* Gather number of samples for the decoded frame. */ framelength = (frame_info.samples >> 1) - lead_trim; if (i == demux_res.num_sample_byte_sizes - 1 && framelength > 0) { - /* Currently limited to at most one frame of tail_trim. - * Seems to be enough. - */ - if (ci->id3->tail_trim == 0 - && sample_duration < (frame_info.samples >> 1)) - { - /* Subtract lead_trim just in case we decode a file with - * only one audio frame with actual data. - */ - framelength = sample_duration - lead_trim; - } - else - { - framelength -= ci->id3->tail_trim; - } + framelength -= ci->id3->tail_trim; } if (framelength > 0) Index: apps/codecs/libm4a/m4a.c =================================================================== --- apps/codecs/libm4a/m4a.c (revision 29714) +++ apps/codecs/libm4a/m4a.c (working copy) @@ -122,6 +122,100 @@ stream->eof=0; } +/* TEST */ +void get_max_sample_byte_size(demux_res_t *demux_res, int *max_frame_size) +{ + unsigned int k; + *max_frame_size = 0; + printf("-- num sizes = %d\n", demux_res->num_sample_byte_sizes); + for (k=0; knum_sample_byte_sizes; ++k) + { + if (demux_res->sample_byte_size[k] > *max_frame_size) + *max_frame_size = demux_res->sample_byte_size[k]; + } + printf("-- max_size = %d\n", *max_frame_size); +} + +#define MAX_TEST_TAB (1<<16) +static int m4a_sync_tab[MAX_TEST_TAB][2]; + +int get_m4a_sync_offset(int frame) +{ + unsigned int i = 0; + for (i=0; i frame) + return -1; + if (m4a_sync_tab[i][0] == frame) + break; + } + //printf("== %6d -> %4d [%6d %9d]\n", frame, i, m4a_sync_tab[i][0], m4a_sync_tab[i][1]); + return m4a_sync_tab[i][1]; +} + +void build_m4a_sync_tab(demux_res_t *demux_res) +{ +#if 0 + /* Version 1: Extract look-up based on sample_byte_size[] and + * get_sample_offset(). + * Pro: Much smaller look-up (often <10 entries). + * Con: Needs sample_byte_size[]. Slow. */ + unsigned int k = 0; + int pos = 0; + int pos_real = 0; + int idx = 0; + memset(m4a_sync_tab, 0, sizeof(m4a_sync_tab)); + printf("-- num_sample_byte_sizes = %d\n", demux_res->num_sample_byte_sizes); + for (k=0; knum_sample_byte_sizes; ++k) + { + pos_real = get_sample_offset(demux_res, k); + if (pos_real > pos) + { + if (idx<10) printf("-- (%d) [%d %d]\n", idx, k, pos_real); + m4a_sync_tab[idx][0] = k; // save frame index + m4a_sync_tab[idx][1] = pos_real; // save desired position + idx++; + pos = pos_real; + } + pos += demux_res->sample_byte_size[k]; + } +#else + /* Version 2: Extract look-up based on sample_to_chunk[] and + * chunk_offset[]. + * Pro: Does not need sample_byte_size[] at all. + * Faster build-up of table. + * Con: Larger look-up table (still ~1/10 of num_sample_byte_sizes[]) */ + unsigned int i = 0; + unsigned int k = 0; + int frame = 0; + int idx = 0; + printf("-- num_chunk_offsets = %d\n", demux_res->num_chunk_offsets); + memset(m4a_sync_tab, 0, sizeof(m4a_sync_tab)); + for (k=1; knum_chunk_offsets; ++k) + { + frame = 0; + for (i=1; inum_sample_to_chunks; ++i) + { + int old_first = demux_res->sample_to_chunk[i-1].first_chunk; + int new_first = demux_res->sample_to_chunk[i ].first_chunk; + + if (demux_res->sample_to_chunk[i].first_chunk > k) + break; + + frame += (new_first - old_first) * demux_res->sample_to_chunk[i-1].num_samples; + } + frame += (k - demux_res->sample_to_chunk[i-1].first_chunk)*demux_res->sample_to_chunk[i-1].num_samples; + + m4a_sync_tab[idx][0] = frame; // save frame index + m4a_sync_tab[idx][1] = demux_res->chunk_offset[k-1]; // save desired position + //if (k<10) printf("-- (%d) [%d %d]\n", idx, m4a_sync_tab[idx][0], m4a_sync_tab[idx][1]); + idx++; + } +#endif + printf("-- m4a_sync_tab has %d entries\n", idx); +} +/* TEST */ + /* This function was part of the original alac decoder implementation */ int get_sample_info(demux_res_t *demux_res, uint32_t samplenum, Index: apps/codecs/libm4a/m4a.h =================================================================== --- apps/codecs/libm4a/m4a.h (revision 29714) +++ apps/codecs/libm4a/m4a.h (working copy) @@ -132,5 +132,11 @@ 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); + +/* TEST */ +int get_m4a_sync_offset(int frame); +void build_m4a_sync_tab(demux_res_t *demux_res); +void get_max_sample_byte_size(demux_res_t *demux_res, int *max_frame_size); +/* TEST */ #endif /* STREAM_H */