]> iEval git - fdkaac.git/blame - src/pcm_readhelper.c
Add VCS fields and fix build-depends
[fdkaac.git] / src / pcm_readhelper.c
CommitLineData
29a8f73f 1/*
2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
4 */
5
6#if HAVE_CONFIG_H
7# include "config.h"
8#endif
9
10#if HAVE_STDINT_H
11# include <stdint.h>
12#endif
13
14#include <stdio.h>
1af8624b 15#include <stdlib.h>
16#include <string.h>
29a8f73f 17#include <stdarg.h>
18#include "pcm_reader.h"
19#include "m4af_endian.h"
1af8624b 20#include "catypes.h"
29a8f73f 21
a7e00a42 22int pcm_read_frames(pcm_reader_t *r, void *data, unsigned nframes)
23{
24 int n;
25 unsigned count = 0;
26 uint8_t *bp = data;
27 unsigned bpf = pcm_get_format(r)->bytes_per_frame;
28
29 do {
30 n = r->vtbl->read_frames(r, bp, nframes - count);
31 if (n > 0) {
32 count += n;
33 bp += n * bpf;
34 }
35 } while (n > 0 && count < nframes);
36 return count;
37}
38
29a8f73f 39int pcm_read(pcm_io_context_t *io, void *buffer, uint32_t size)
40{
41 int rc;
42 uint32_t count = 0;
a7e00a42 43 uint8_t *bp = buffer;
29a8f73f 44
45 do {
a7e00a42 46 rc = io->vtbl->read(io->cookie, bp, size - count);
47 if (rc > 0) {
29a8f73f 48 count += rc;
a7e00a42 49 bp += rc;
50 }
29a8f73f 51 } while (rc > 0 && count < size);
52 return count > 0 ? count : rc;
53}
54
55int pcm_skip(pcm_io_context_t *io, int64_t count)
56{
57 char buff[8192];
58 int rc;
59 pcm_io_vtbl_t *vp = io->vtbl;
60
61 if (count == 0 || pcm_seek(io, count, SEEK_CUR) >= 0)
62 return 0;
63 do {
64 if ((rc = vp->read(io->cookie, buff, count > 8192 ? 8192 : count)) > 0)
65 count -= rc;
66 } while (rc > 0 && count > 0);
67
68 return count == 0 ? 0 : -1;
69}
70
71int pcm_read16le(pcm_io_context_t *io, uint16_t *value)
72{
73 if (pcm_read(io, value, 2) == 2) {
74 *value = m4af_ltoh16(*value);
75 return 0;
76 }
77 return -1;
78}
79
80int pcm_read16be(pcm_io_context_t *io, uint16_t *value)
81{
82 if (pcm_read(io, value, 2) == 2) {
83 *value = m4af_btoh16(*value);
84 return 0;
85 }
86 return -1;
87}
88
89int pcm_read32le(pcm_io_context_t *io, uint32_t *value)
90{
91 if (pcm_read(io, value, 4) == 4) {
92 *value = m4af_ltoh32(*value);
93 return 0;
94 }
95 return -1;
96}
97
98int pcm_read32be(pcm_io_context_t *io, uint32_t *value)
99{
100 if (pcm_read(io, value, 4) == 4) {
101 *value = m4af_btoh32(*value);
102 return 0;
103 }
104 return -1;
105}
106
107int pcm_read64le(pcm_io_context_t *io, uint64_t *value)
108{
109 if (pcm_read(io, value, 8) == 8) {
110 *value = m4af_ltoh64(*value);
111 return 0;
112 }
113 return -1;
114}
115
116int pcm_read64be(pcm_io_context_t *io, uint64_t *value)
117{
118 if (pcm_read(io, value, 8) == 8) {
119 *value = m4af_btoh64(*value);
120 return 0;
121 }
122 return -1;
123}
124
125int pcm_scanl(pcm_io_context_t *io, const char *fmt, ...)
126{
127 int c, count = 0;
128 va_list ap;
129
130 va_start(ap, fmt);
131 while ((c = *fmt++)) {
132 switch (c) {
133 case 'S':
134 TRY_IO(pcm_read16le(io, va_arg(ap, uint16_t*)));
135 ++count;
136 break;
137 case 'L':
138 TRY_IO(pcm_read32le(io, va_arg(ap, uint32_t*)));
139 ++count;
140 break;
141 case 'Q':
142 TRY_IO(pcm_read64le(io, va_arg(ap, uint64_t*)));
143 ++count;
144 break;
145 }
146 }
147FAIL:
148 va_end(ap);
149 return count;
150}
151
152int pcm_scanb(pcm_io_context_t *io, const char *fmt, ...)
153{
154 int c, count = 0;
155 va_list ap;
156
157 va_start(ap, fmt);
158 while ((c = *fmt++)) {
159 switch (c) {
160 case 'S':
161 TRY_IO(pcm_read16be(io, va_arg(ap, uint16_t*)));
162 ++count;
163 break;
164 case 'L':
165 TRY_IO(pcm_read32be(io, va_arg(ap, uint32_t*)));
166 ++count;
167 break;
168 case 'Q':
169 TRY_IO(pcm_read64be(io, va_arg(ap, uint64_t*)));
170 ++count;
171 break;
172 }
173 }
174FAIL:
175 va_end(ap);
176 return count;
177}
1af8624b 178
179static
180int channel_compare(const void *a, const void *b)
181{
182 return (*(const uint8_t **)a)[0] - (*(const uint8_t **)b)[0];
183}
184
185void apple_translate_channel_labels(uint8_t *channels, unsigned n)
186{
187 unsigned i;
188 char *has_side = strpbrk((char*)channels, "\x0A\x0B");
189
190 for (i = 0; i < n; ++i) {
191 switch (channels[i]) {
192 case kAudioChannelLabel_LeftSurround:
193 case kAudioChannelLabel_RightSurround:
194 if (!has_side) channels[i] += 5; // map to SL/SR
195 break;
196 case kAudioChannelLabel_RearSurroundLeft:
197 case kAudioChannelLabel_RearSurroundRight:
198 if (!has_side) channels[i] -= 28; // map to BL/BR
199 break;
200 case kAudioChannelLabel_Mono:
201 channels[i] = kAudioChannelLabel_Center;
202 break;
203 }
204 }
205}
206
207int apple_chan_chunk(pcm_io_context_t *io, uint32_t chunk_size,
208 pcm_sample_description_t *fmt, uint8_t *mapping)
209{
210 /*
211 * Although FDK encoder supports upto 5.1ch, we handle upto
212 * 8 channels here.
213 */
214 uint32_t i, mChannelLayoutTag, mChannelBitmap, mNumberChannelDescriptions;
215 uint32_t mask = 0;
216 const uint32_t nchannels = fmt->channels_per_frame;
217 uint8_t channels[9] = { 0 };
218 uint8_t *index[8] = { 0 };
219 const char *layout = 0;
220
221 ENSURE(chunk_size >= 12);
222 TRY_IO(pcm_scanb(io, "LLL", &mChannelLayoutTag, &mChannelBitmap,
223 &mNumberChannelDescriptions) != 3);
224
225 switch (mChannelLayoutTag) {
226 case kAudioChannelLayoutTag_UseChannelBitmap:
57aa9141 227 ENSURE(bitcount(mChannelBitmap) == nchannels);
1af8624b 228 TRY_IO(pcm_skip(io, chunk_size - 12));
229 fmt->channel_mask = mChannelBitmap;
230 for (i = 0; i < nchannels; ++i)
231 mapping[i] = i;
232 return 0;
233 case kAudioChannelLayoutTag_UseChannelDescriptions:
234 ENSURE(mNumberChannelDescriptions == nchannels);
235 ENSURE(chunk_size >= 12 + nchannels * 20);
236 for (i = 0; i < mNumberChannelDescriptions; ++i) {
237 uint32_t mChannelLabel;
238 TRY_IO(pcm_read32be(io, &mChannelLabel));
239 ENSURE(mChannelLabel && mChannelLabel <= 0xff);
240 channels[i] = mChannelLabel;
241 TRY_IO(pcm_skip(io, 16));
242 }
243 TRY_IO(pcm_skip(io, chunk_size - 12 - nchannels * 20));
244 apple_translate_channel_labels(channels, nchannels);
245 for (i = 0; i < nchannels; ++i)
246 if (channels[i] > kAudioChannelLabel_TopBackLeft)
247 goto FAIL;
248 break;
249 default:
250 ENSURE((mChannelLayoutTag & 0xffff) == nchannels);
251 TRY_IO(pcm_skip(io, chunk_size - 12));
252
253 switch (mChannelLayoutTag) {
254 /* 1ch */
255 case kAudioChannelLayoutTag_Mono:
256 layout = "\x03"; break;
257 /* 1.1ch */
258 case kAudioChannelLayoutTag_AC3_1_0_1:
259 layout = "\x03\x04"; break;
260 /* 2ch */
261 case kAudioChannelLayoutTag_Stereo:
262 case kAudioChannelLayoutTag_MatrixStereo:
263 case kAudioChannelLayoutTag_Binaural:
264 layout = "\x01\x02"; break;
265 /* 2.1ch */
266 case kAudioChannelLayoutTag_DVD_4:
267 layout = "\x01\x02\x04"; break;
268 /* 3ch */
269 case kAudioChannelLayoutTag_MPEG_3_0_A:
270 layout = "\x01\x02\x03"; break;
271 case kAudioChannelLayoutTag_AC3_3_0:
272 layout = "\x01\x03\x02"; break;
273 case kAudioChannelLayoutTag_MPEG_3_0_B:
274 layout = "\x03\x01\x02"; break;
275 case kAudioChannelLayoutTag_ITU_2_1:
276 layout = "\x01\x02\x09"; break;
277 /* 3.1ch */
278 case kAudioChannelLayoutTag_DVD_10:
279 layout = "\x01\x02\x03\x04"; break;
280 case kAudioChannelLayoutTag_AC3_3_0_1:
281 layout = "\x01\x03\x02\x04"; break;
282 case kAudioChannelLayoutTag_DVD_5:
283 layout = "\x01\x02\x04\x09"; break;
284 case kAudioChannelLayoutTag_AC3_2_1_1:
285 layout = "\x01\x02\x09\x04"; break;
286 /* 4ch */
287 case kAudioChannelLayoutTag_Quadraphonic:
288 case kAudioChannelLayoutTag_ITU_2_2:
289 layout = "\x01\x02\x0A\x0B"; break;
290 case kAudioChannelLayoutTag_MPEG_4_0_A:
291 layout = "\x01\x02\x03\x09"; break;
292 case kAudioChannelLayoutTag_MPEG_4_0_B:
293 layout = "\x03\x01\x02\x09"; break;
294 case kAudioChannelLayoutTag_AC3_3_1:
295 layout = "\x01\x03\x02\x09"; break;
296 /* 4.1ch */
297 case kAudioChannelLayoutTag_DVD_6:
298 layout = "\x01\x02\x04\x0A\x0B"; break;
299 case kAudioChannelLayoutTag_DVD_18:
300 layout = "\x01\x02\x0A\x0B\x04"; break;
301 case kAudioChannelLayoutTag_DVD_11:
302 layout = "\x01\x02\x03\x04\x09"; break;
303 case kAudioChannelLayoutTag_AC3_3_1_1:
304 layout = "\x01\x03\x02\x09\x04"; break;
305 /* 5ch */
306 case kAudioChannelLayoutTag_MPEG_5_0_A:
307 layout = "\x01\x02\x03\x0A\x0B"; break;
308 case kAudioChannelLayoutTag_Pentagonal:
309 case kAudioChannelLayoutTag_MPEG_5_0_B:
310 layout = "\x01\x02\x0A\x0B\x03"; break;
311 case kAudioChannelLayoutTag_MPEG_5_0_C:
312 layout = "\x01\x03\x02\x0A\x0B"; break;
313 case kAudioChannelLayoutTag_MPEG_5_0_D:
314 layout = "\x03\x01\x02\x0A\x0B"; break;
315 /* 5.1ch */
316 case kAudioChannelLayoutTag_MPEG_5_1_A:
317 layout = "\x01\x02\x03\x04\x0A\x0B"; break;
318 case kAudioChannelLayoutTag_MPEG_5_1_B:
319 layout = "\x01\x02\x0A\x0B\x03\x04"; break;
320 case kAudioChannelLayoutTag_MPEG_5_1_C:
321 layout = "\x01\x03\x02\x0A\x0B\x04"; break;
322 case kAudioChannelLayoutTag_MPEG_5_1_D:
323 layout = "\x03\x01\x02\x0A\x0B\x04"; break;
324 /* 6ch */
325 case kAudioChannelLayoutTag_Hexagonal:
326 case kAudioChannelLayoutTag_AudioUnit_6_0:
327 layout = "\x01\x02\x0A\x0B\x03\x09"; break;
328 case kAudioChannelLayoutTag_AAC_6_0:
329 layout = "\x03\x01\x02\x0A\x0B\x09"; break;
330 /* 6.1ch */
331 case kAudioChannelLayoutTag_MPEG_6_1_A:
332 layout = "\x01\x02\x03\x04\x0A\x0B\x09"; break;
333 case kAudioChannelLayoutTag_AAC_6_1:
334 layout = "\x03\x01\x02\x0A\x0B\x09\x04"; break;
335 /* 7ch */
336 case kAudioChannelLayoutTag_AudioUnit_7_0:
337 layout = "\x01\x02\x0A\x0B\x03\x05\x06"; break;
338 case kAudioChannelLayoutTag_AudioUnit_7_0_Front:
339 layout = "\x01\x02\x0A\x0B\x03\x07\x08"; break;
340 case kAudioChannelLayoutTag_AAC_7_0:
341 layout = "\x03\x01\x02\x0A\x0B\x05\x06"; break;
342 /* 7.1ch */
343 case kAudioChannelLayoutTag_MPEG_7_1_A:
344 layout = "\x01\x02\x03\x04\x0A\x0B\x07\x08"; break;
345 case kAudioChannelLayoutTag_MPEG_7_1_B:
346 layout = "\x03\x07\x08\x01\x02\x05\x06\x04"; break;
347 case kAudioChannelLayoutTag_MPEG_7_1_C:
348 layout = "\x01\x02\x03\x04\x0A\x0B\x05\x06"; break;
349 case kAudioChannelLayoutTag_Emagic_Default_7_1:
350 layout = "\x01\x02\x0A\x0B\x03\x04\x07\x08"; break;
351 /* 8ch */
352 case kAudioChannelLayoutTag_Octagonal:
353 layout = "\x01\x02\x05\x06\x03\x09\x0A\x0B"; break;
354 case kAudioChannelLayoutTag_AAC_Octagonal:
355 layout = "\x03\x01\x02\x0A\x0B\x05\x06\x09"; break;
356 default:
357 goto FAIL;
358 }
359 strcpy((char*)channels, layout);
360 }
361
362 for (i = 0; i < nchannels; ++i)
363 mask |= 1 << (channels[i] - 1);
364 fmt->channel_mask = mask;
365 ENSURE(bitcount(mask) == nchannels);
366
367 for (i = 0; i < nchannels; ++i)
368 index[i] = channels + i;
369 qsort(index, nchannels, sizeof(char*), channel_compare);
370 for (i = 0; i < nchannels; ++i)
371 mapping[i] = index[i] - channels;
372
373 return 0;
374FAIL:
375 return -1;
376}
This page took 0.054541 seconds and 4 git commands to generate.