diff options
Diffstat (limited to 'apps/codecs/libm4a/m4a.c')
-rw-r--r-- | apps/codecs/libm4a/m4a.c | 237 |
1 files changed, 51 insertions, 186 deletions
diff --git a/apps/codecs/libm4a/m4a.c b/apps/codecs/libm4a/m4a.c index 8c4b172bc2..836cdafda3 100644 --- a/apps/codecs/libm4a/m4a.c +++ b/apps/codecs/libm4a/m4a.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2005 Dave Chapman | 10 | * Copyright (C) 2005 Dave Chapman, 2011 Andree Buschmann |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
@@ -122,148 +122,46 @@ void stream_create(stream_t *stream,struct codec_api* ci) | |||
122 | stream->eof=0; | 122 | stream->eof=0; |
123 | } | 123 | } |
124 | 124 | ||
125 | /* This function was part of the original alac decoder implementation */ | 125 | /* Check if there is a dedicated byte position contained for the given frame. |
126 | 126 | * Return this byte position in case of success or return -1. This allows to | |
127 | int get_sample_info(demux_res_t *demux_res, uint32_t samplenum, | 127 | * skip empty samples. */ |
128 | uint32_t *sample_duration, | 128 | int m4a_check_sample_offset(demux_res_t *demux_res, uint32_t frame) |
129 | uint32_t *sample_byte_size) | ||
130 | { | 129 | { |
131 | unsigned int duration_index_accum = 0; | 130 | uint32_t i = 0; |
132 | unsigned int duration_cur_index = 0; | 131 | for (i=0; i<demux_res->num_lookup_table; ++i) |
133 | 132 | { | |
134 | if (samplenum >= demux_res->num_sample_byte_sizes) { | 133 | if (demux_res->lookup_table[i].sample > frame || |
135 | return 0; | 134 | demux_res->lookup_table[i].offset == 0) |
136 | } | 135 | return -1; |
137 | 136 | if (demux_res->lookup_table[i].sample == frame) | |
138 | if (!demux_res->num_time_to_samples) { | 137 | break; |
139 | return 0; | ||
140 | } | ||
141 | |||
142 | while ((demux_res->time_to_sample[duration_cur_index].sample_count | ||
143 | + duration_index_accum) <= samplenum) { | ||
144 | duration_index_accum += | ||
145 | demux_res->time_to_sample[duration_cur_index].sample_count; | ||
146 | |||
147 | duration_cur_index++; | ||
148 | if (duration_cur_index >= demux_res->num_time_to_samples) { | ||
149 | return 0; | ||
150 | } | ||
151 | } | 138 | } |
152 | 139 | return demux_res->lookup_table[i].offset; | |
153 | *sample_duration = | ||
154 | demux_res->time_to_sample[duration_cur_index].sample_duration; | ||
155 | *sample_byte_size = demux_res->sample_byte_size[samplenum]; | ||
156 | |||
157 | return 1; | ||
158 | } | 140 | } |
159 | 141 | ||
160 | unsigned int get_sample_offset(demux_res_t *demux_res, uint32_t sample) | 142 | /* Find the exact or preceding frame in lookup_table[]. Return both frame |
143 | * and byte position of this match. */ | ||
144 | static void gather_offset(demux_res_t *demux_res, uint32_t *frame, uint32_t *offset) | ||
161 | { | 145 | { |
162 | uint32_t chunk = 1; | 146 | uint32_t i = 0; |
163 | uint32_t range_samples = 0; | 147 | for (i=0; i<demux_res->num_lookup_table; ++i) |
164 | uint32_t total_samples = 0; | ||
165 | uint32_t chunk_sample; | ||
166 | uint32_t prev_chunk; | ||
167 | uint32_t prev_chunk_samples; | ||
168 | uint32_t file_offset; | ||
169 | uint32_t i; | ||
170 | |||
171 | /* First check we have the appropriate metadata - we should always | ||
172 | * have it. | ||
173 | */ | ||
174 | |||
175 | if (sample >= demux_res->num_sample_byte_sizes || | ||
176 | !demux_res->num_sample_to_chunks || | ||
177 | !demux_res->num_chunk_offsets) | ||
178 | { | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | /* Locate the chunk containing the sample */ | ||
183 | |||
184 | prev_chunk = demux_res->sample_to_chunk[0].first_chunk; | ||
185 | prev_chunk_samples = demux_res->sample_to_chunk[0].num_samples; | ||
186 | |||
187 | for (i = 1; i < demux_res->num_sample_to_chunks; i++) | ||
188 | { | 148 | { |
189 | chunk = demux_res->sample_to_chunk[i].first_chunk; | 149 | if (demux_res->lookup_table[i].offset == 0) |
190 | range_samples = (chunk - prev_chunk) * prev_chunk_samples; | 150 | break; |
191 | 151 | if (demux_res->lookup_table[i].sample > *frame) | |
192 | if (sample < total_samples + range_samples) | ||
193 | { | ||
194 | break; | 152 | break; |
195 | } | ||
196 | |||
197 | total_samples += range_samples; | ||
198 | prev_chunk = demux_res->sample_to_chunk[i].first_chunk; | ||
199 | prev_chunk_samples = demux_res->sample_to_chunk[i].num_samples; | ||
200 | } | ||
201 | |||
202 | if (prev_chunk_samples > 0 && | ||
203 | sample >= demux_res->sample_to_chunk[0].num_samples) | ||
204 | { | ||
205 | chunk = prev_chunk + (sample - total_samples) / prev_chunk_samples; | ||
206 | } | ||
207 | else | ||
208 | { | ||
209 | chunk = 1; | ||
210 | } | ||
211 | |||
212 | /* Get sample of the first sample in the chunk */ | ||
213 | |||
214 | chunk_sample = total_samples + (chunk - prev_chunk) * prev_chunk_samples; | ||
215 | |||
216 | /* Get offset in file */ | ||
217 | |||
218 | if (chunk > demux_res->num_chunk_offsets) | ||
219 | { | ||
220 | file_offset = demux_res->chunk_offset[demux_res->num_chunk_offsets - 1]; | ||
221 | } | ||
222 | else | ||
223 | { | ||
224 | file_offset = demux_res->chunk_offset[chunk - 1]; | ||
225 | } | ||
226 | |||
227 | if (chunk_sample > sample) | ||
228 | { | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | for (i = chunk_sample; i < sample; i++) | ||
233 | { | ||
234 | file_offset += demux_res->sample_byte_size[i]; | ||
235 | } | ||
236 | |||
237 | if (file_offset > demux_res->mdat_offset + demux_res->mdat_len) | ||
238 | { | ||
239 | return 0; | ||
240 | } | 153 | } |
241 | 154 | i = (i>0) ? i-1 : 0; /* We want the last chunk _before_ *frame. */ | |
242 | return file_offset; | 155 | *frame = demux_res->lookup_table[i].sample; |
156 | *offset = demux_res->lookup_table[i].offset; | ||
243 | } | 157 | } |
244 | 158 | ||
245 | /* Seek to the sample containing sound_sample_loc. Return 1 on success | 159 | /* Seek to desired sound sample location. Return 1 on success (and modify |
246 | * (and modify sound_samples_done and current_sample), 0 if failed. | 160 | * sound_samples_done and current_sample), 0 if failed. |
247 | * | ||
248 | * Seeking uses the following arrays: | ||
249 | * | ||
250 | * 1) the time_to_sample array contains the duration (in sound samples) | ||
251 | * of each sample of data. | ||
252 | * | ||
253 | * 2) the sample_byte_size array contains the length in bytes of each | ||
254 | * sample. | ||
255 | * | ||
256 | * 3) the sample_to_chunk array contains information about which chunk | ||
257 | * of samples each sample belongs to. | ||
258 | * | ||
259 | * 4) the chunk_offset array contains the file offset of each chunk. | ||
260 | * | ||
261 | * So find the sample number we are going to seek to (using time_to_sample) | ||
262 | * and then find the offset in the file (using sample_to_chunk, | ||
263 | * chunk_offset sample_byte_size, in that order.). | ||
264 | * | 161 | * |
265 | */ | 162 | * Find the sample (=frame) that contains the given sound sample, find a best |
266 | unsigned int alac_seek(demux_res_t* demux_res, stream_t* stream, | 163 | * fit for this sample in the lookup_table[], seek to the byte position. */ |
164 | unsigned int m4a_seek(demux_res_t* demux_res, stream_t* stream, | ||
267 | uint32_t sound_sample_loc, uint32_t* sound_samples_done, | 165 | uint32_t sound_sample_loc, uint32_t* sound_samples_done, |
268 | int* current_sample) | 166 | int* current_sample) |
269 | { | 167 | { |
@@ -300,8 +198,8 @@ unsigned int alac_seek(demux_res_t* demux_res, stream_t* stream, | |||
300 | ++i; | 198 | ++i; |
301 | } | 199 | } |
302 | 200 | ||
303 | /* We know the new block, now calculate the file position. */ | 201 | /* We know the new sample (=frame), now calculate the file position. */ |
304 | new_pos = get_sample_offset(demux_res, new_sample); | 202 | gather_offset(demux_res, &new_sample, &new_pos); |
305 | 203 | ||
306 | /* We know the new file position, so let's try to seek to it */ | 204 | /* We know the new file position, so let's try to seek to it */ |
307 | if (stream->ci->seek_buffer(new_pos)) | 205 | if (stream->ci->seek_buffer(new_pos)) |
@@ -319,71 +217,38 @@ unsigned int alac_seek(demux_res_t* demux_res, stream_t* stream, | |||
319 | * | 217 | * |
320 | * Seeking uses the following arrays: | 218 | * Seeking uses the following arrays: |
321 | * | 219 | * |
322 | * 1) the chunk_offset array contains the file offset of each chunk. | 220 | * 1) the lookup_table array contains the file offset for the first sample |
323 | * | 221 | * of each chunk. |
324 | * 2) the sample_to_chunk array contains information about which chunk | ||
325 | * of samples each sample belongs to. | ||
326 | * | ||
327 | * 3) the sample_byte_size array contains the length in bytes of each | ||
328 | * sample. | ||
329 | * | 222 | * |
330 | * 4) the time_to_sample array contains the duration (in sound samples) | 223 | * 2) the time_to_sample array contains the duration (in sound samples) |
331 | * of each sample of data. | 224 | * of each sample of data. |
332 | * | 225 | * |
333 | * Locate the chunk containing location (using chunk_offset), find the | 226 | * Locate the chunk containing location (using lookup_table), find the first |
334 | * sample of that chunk (using sample_to_chunk) and finally the location | 227 | * sample of that chunk (using lookup_table). Then use time_to_sample to |
335 | * of that sample (using sample_byte_size). Then use time_to_sample to | ||
336 | * calculate the sound_samples_done value. | 228 | * calculate the sound_samples_done value. |
337 | */ | 229 | */ |
338 | unsigned int alac_seek_raw(demux_res_t* demux_res, stream_t* stream, | 230 | unsigned int m4a_seek_raw(demux_res_t* demux_res, stream_t* stream, |
339 | uint32_t file_loc, uint32_t* sound_samples_done, | 231 | uint32_t file_loc, uint32_t* sound_samples_done, |
340 | int* current_sample) | 232 | int* current_sample) |
341 | { | 233 | { |
342 | uint32_t chunk_sample = 0; /* Holds the chunk/frame index. */ | 234 | uint32_t i; |
343 | uint32_t total_samples = 0; /* Sums up total amount of chunks/frames. */ | 235 | uint32_t chunk_sample = 0; |
344 | uint32_t new_sound_sample = 0; /* Sums up total amount of samples. */ | 236 | uint32_t total_samples = 0; |
237 | uint32_t new_sound_sample = 0; | ||
238 | uint32_t tmp_dur; | ||
239 | uint32_t tmp_cnt; | ||
345 | uint32_t new_pos; | 240 | uint32_t new_pos; |
346 | uint32_t chunk; | ||
347 | uint32_t i, tmp_dur, tmp_cnt; | ||
348 | |||
349 | /* There is no metadata available to perform raw seek. */ | ||
350 | if (!demux_res->num_chunk_offsets || !demux_res->num_sample_to_chunks) | ||
351 | { | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | /* Locate the chunk containing file_loc. */ | ||
356 | chunk = 0; | ||
357 | while (chunk < demux_res->num_chunk_offsets) | ||
358 | { | ||
359 | if (file_loc < demux_res->chunk_offset[chunk]) | ||
360 | { | ||
361 | break; | ||
362 | } | ||
363 | ++chunk; | ||
364 | } | ||
365 | new_pos = demux_res->chunk_offset[chunk > 0 ? chunk - 1 : 0]; | ||
366 | 241 | ||
367 | /* Get the first sample of the chunk. */ | 242 | /* We know the desired byte offset, search for the chunk right before. |
368 | i = 1; | 243 | * Return the associated sample to this chunk as chunk_sample. */ |
369 | sample_to_chunk_t *tab1 = demux_res->sample_to_chunk; | 244 | for (i=0; i < demux_res->num_lookup_table; ++i) |
370 | while (i < demux_res->num_sample_to_chunks) | ||
371 | { | 245 | { |
372 | if (chunk <= tab1[i].first_chunk) | 246 | if (demux_res->lookup_table[i].offset > file_loc) |
373 | { | ||
374 | break; | 247 | break; |
375 | } | ||
376 | chunk_sample += tab1[i-1].num_samples * (tab1[i].first_chunk - tab1[i-1].first_chunk); | ||
377 | ++i; | ||
378 | } | ||
379 | chunk_sample += (chunk - tab1[i-1].first_chunk) * tab1[i-1].num_samples; | ||
380 | |||
381 | /* Get the position within the chunk. */ | ||
382 | while (chunk_sample < demux_res->num_sample_byte_sizes && | ||
383 | file_loc >= new_pos + demux_res->sample_byte_size[chunk_sample]) | ||
384 | { | ||
385 | new_pos += demux_res->sample_byte_size[chunk_sample++]; | ||
386 | } | 248 | } |
249 | i = (i>0) ? i-1 : 0; /* We want the last chunk _before_ file_loc. */ | ||
250 | chunk_sample = demux_res->lookup_table[i].sample; | ||
251 | new_pos = demux_res->lookup_table[i].offset; | ||
387 | 252 | ||
388 | /* Get sound sample offset. */ | 253 | /* Get sound sample offset. */ |
389 | i = 0; | 254 | i = 0; |