summaryrefslogtreecommitdiff
path: root/audio_codec/wfd_aac_decoder/helix_aac_decode.c (plain)
blob: ae32386521c101d4f8115220184b127477ac9a68
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <fcntl.h>
5#include <unistd.h>
6#include <pthread.h>
7#include <sys/ioctl.h>
8#include <dlfcn.h>
9#include <sys/mman.h>
10#include <cutils/properties.h>
11
12
13
14#include "aaccommon.h"
15#include "aacdec.h"
16#include "../../amadec/adec-armdec-mgt.h"
17
18
19int AACDataSource = 1;
20static HAACDecoder hAACDecoder;
21static HAACIOBuf hAACIOBuf = NULL;
22
23static int mute_pcm_bytes;
24/* check the normal frame size */
25static unsigned last_frm_size;
26static unsigned cur_frm_size;
27static int lastFrameLen ;
28static int lastSampPerFrm ;
29
30#define FRAME_RECORD_NUM 20
31static unsigned error_count = 0;
32static unsigned mute_pcm_thread;
33static unsigned his_index;
34static unsigned frame_length_his[FRAME_RECORD_NUM];
35
36static unsigned stream_in_offset = 0;
37static unsigned enable_debug_print = 0;
38/* Channel definitions */
39#define FRONT_CENTER (0)
40#define FRONT_LEFT (1)
41#define FRONT_RIGHT (2)
42#define SIDE_LEFT (3)
43#define SIDE_RIGHT (4)
44#define BACK_LEFT (5)
45#define LFE_CHANNEL (6)
46
47
48
49
50
51#define ASTREAM_DEV "/dev/uio0"
52#define ASTREAM_ADDR "/sys/class/astream/astream-dev/uio0/maps/map0/addr"
53#define ASTREAM_SIZE "/sys/class/astream/astream-dev/uio0/maps/map0/size"
54#define ASTREAM_OFFSET "/sys/class/astream/astream-dev/uio0/maps/map0/offset"
55
56
57
58#define AIU_AIFIFO_CTRL 0x1580
59#define AIU_AIFIFO_STATUS 0x1581
60#define AIU_AIFIFO_GBIT 0x1582
61#define AIU_AIFIFO_CLB 0x1583
62#define AIU_MEM_AIFIFO_START_PTR 0x1584
63#define AIU_MEM_AIFIFO_CURR_PTR 0x1585
64#define AIU_MEM_AIFIFO_END_PTR 0x1586
65#define AIU_MEM_AIFIFO_BYTES_AVAIL 0x1587
66#define AIU_MEM_AIFIFO_CONTROL 0x1588
67#define AIU_MEM_AIFIFO_MAN_WP 0x1589
68#define AIU_MEM_AIFIFO_MAN_RP 0x158a
69#define AIU_MEM_AIFIFO_LEVEL 0x158b
70#define AIU_MEM_AIFIFO_BUF_CNTL 0x158c
71#define AIU_MEM_AIFIFO_BUF_WRAP_COUNT 0x158d
72#define AIU_MEM_AIFIFO2_BUF_WRAP_COUNT 0x158e
73#define AIU_MEM_AIFIFO_MEM_CTL 0x158f
74
75volatile unsigned* reg_base = 0;
76#define READ_MPEG_REG(reg) reg_base[reg-AIU_AIFIFO_CTRL]
77#define WRITE_MPEG_REG(reg, val) reg_base[reg-AIU_AIFIFO_CTRL]=val
78#define AIFIFO_READY (((READ_MPEG_REG(AIU_MEM_AIFIFO_CONTROL)&(1<<9))))
79#define min(x,y) ((x<y)?(x):(y))
80static int fd_uio = -1;
81static volatile void *memmap = MAP_FAILED;
82static int phys_size;
83static volatile int exit_flag = 0;
84static unsigned long amsysfs_get_sysfs_ulong(const char *path)
85{
86 int fd;
87 char bcmd[24] = "";
88 unsigned long num = 0;
89 if ((fd = open(path, O_RDONLY)) >= 0) {
90 read(fd, bcmd, sizeof(bcmd));
91 num = strtoul(bcmd, NULL, 0);
92 close(fd);
93 } else {
94 audio_codec_print("unable to open file %s,", path);
95 }
96 return num;
97}
98static unsigned long get_num_infile(char *file)
99{
100 return amsysfs_get_sysfs_ulong(file);
101}
102
103static int uio_init()
104{
105 int pagesize = getpagesize();
106 int phys_start;
107 int phys_offset;
108
109
110 fd_uio = open(ASTREAM_DEV, O_RDWR);
111 if (fd_uio < 0) {
112 audio_codec_print("error open UIO 0\n");
113 return -1;
114 }
115 phys_start = get_num_infile(ASTREAM_ADDR);
116 phys_size = get_num_infile(ASTREAM_SIZE);
117 phys_offset = get_num_infile(ASTREAM_OFFSET);
118
119 audio_codec_print("add=%08x, size=%08x, offset=%08x\n", phys_start, phys_size, phys_offset);
120
121 phys_size = (phys_size + pagesize - 1) & (~(pagesize - 1));
122 memmap = mmap(NULL, phys_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_uio, 0 * pagesize);
123
124 audio_codec_print("memmap = %x , pagesize = %x\n", memmap, pagesize);
125 if (memmap == MAP_FAILED) {
126 audio_codec_print("map /dev/uio0 failed\n");
127 return -1;
128 }
129
130 if (phys_offset == 0)
131 phys_offset = (AIU_AIFIFO_CTRL*4)&(pagesize-1);
132 reg_base = memmap + phys_offset;
133 return 0;
134}
135
136#define EXTRA_DATA_SIZE 128
137
138static inline void waiting_bits(int bits)
139{
140 int bytes;
141 bytes = READ_MPEG_REG(AIU_MEM_AIFIFO_BYTES_AVAIL);
142 while (bytes * 8 < bits && !exit_flag) {
143 usleep(1000);
144 bytes = READ_MPEG_REG(AIU_MEM_AIFIFO_BYTES_AVAIL);
145 }
146}
147
148int read_buffer(unsigned char *buffer, int size)
149{
150 int bytes;
151 int len;
152 unsigned char *p = buffer;
153 int tmp;
154 int space;
155 int i;
156 int wait_times = 0, fifo_ready_wait = 0;
157
158 int iii;
159
160 iii = READ_MPEG_REG(AIU_MEM_AIFIFO_LEVEL) - EXTRA_DATA_SIZE;
161 if ((size >= iii)) {
162 return 0;
163 }
164
165 // adec_print("read_buffer start while iii= %d!!\n", iii);
166 for (len = 0; len < size;) {
167 space = (size - len);
168 bytes = READ_MPEG_REG(AIU_MEM_AIFIFO_BYTES_AVAIL);
169 //adec_print("read_buffer start AIU_MEM_AIFIFO_BYTES_AVAIL bytes= %d!!\n", bytes);
170 wait_times = 0;
171 while (bytes == 0) {
172 waiting_bits((space > 128) ? 128 * 8 : (space * 8)); /*wait 32 bytes,if the space is less than 32 bytes,wait the space bits*/
173 bytes = READ_MPEG_REG(AIU_MEM_AIFIFO_BYTES_AVAIL);
174
175 audio_codec_print("read_buffer while AIU_MEM_AIFIFO_BYTES_AVAIL = %d!!\n", bytes);
176 wait_times++;
177 if (wait_times > 10) {
178 audio_codec_print("goto out!!\n");
179 goto out;
180 }
181 }
182 bytes = min(space, bytes);
183
184 //adec_print("read_buffer while bytes = %d!!\n", bytes);
185 for (i = 0; i < bytes; i++) {
186 while (!AIFIFO_READY) {
187 fifo_ready_wait++;
188 usleep(1000);
189 if (fifo_ready_wait > 100) {
190 audio_codec_print("FATAL err,AIFIFO is not ready,check!!\n");
191 return 0;
192 }
193 }
194 WRITE_MPEG_REG(AIU_AIFIFO_GBIT, 8);
195 tmp = READ_MPEG_REG(AIU_AIFIFO_GBIT);
196 //adec_print("read_buffer while tmp = %d!!\n", tmp);
197
198 *p++ = tmp & 0xff;
199 fifo_ready_wait = 0;
200
201 }
202 len += bytes;
203 }
204out:
205 stream_in_offset += len;
206 return len;
207}
208int get_audiobuf_level()
209{
210 int level = 0;
211 level = READ_MPEG_REG(AIU_MEM_AIFIFO_LEVEL) - EXTRA_DATA_SIZE;
212 if (level < 0) {
213 level = 0;
214 }
215 return level;
216}
217
218
219static unsigned get_frame_size()
220{
221 int i;
222 unsigned sum = 0;
223 unsigned valid_his_num = 0;
224 for (i = 0; i < FRAME_RECORD_NUM; i++) {
225 if (frame_length_his[i] > 0) {
226 valid_his_num ++;
227 sum += frame_length_his[i];
228 }
229 }
230
231 if (valid_his_num == 0) {
232 return 0;
233 }
234
235 return sum / valid_his_num;
236}
237
238unsigned get_audio_inbuf_latency(int bytesin)
239{
240 int frame_size = 0;
241 int latency_ms = 0;
242 frame_size = get_frame_size();
243 if (frame_size > 0) {
244 latency_ms = bytesin * 1024 / (frame_size * 48);
245 }
246 return latency_ms;
247}
248
249static HAACDecoder aac_init_decoder()
250{
251 return AACInitDecoder();
252}
253static HAACIOBuf aac_init_iobuf()
254{
255 return (HAACIOBuf)calloc(1, sizeof(AACIOBuf));
256}
257#define AUDIO_BUFFER_REMAINED 128
258static void aac_refill_buffer(HAACIOBuf hIOBuf)
259{
260 AACIOBuf *IOBuf = (AACIOBuf*)hIOBuf;
261 int bytes_expected;
262 int read_bytes;
263 int read_level_count = 0;
264 int buf_level = 0;
265 int retry_time = 0;
266
267start_read:
268 if (exit_flag) {
269 return ;
270 }
271 do {
272 buf_level = get_audiobuf_level();
273 if (buf_level <= 0) {
274 break;
275 }
276
277 if (IOBuf->bytesLeft > 0) {
278 while (IOBuf->bytesLeft > AAC_INPUTBUF_SIZE) {
279 ;
280 }
281 memcpy(IOBuf->readBuf, IOBuf->readPtr, IOBuf->bytesLeft);
282 }
283
284 while (IOBuf->bytesLeft < 0) {
285 printk("IOBuf->bytesLeft < 0\n", IOBuf->bytesLeft);
286 }
287
288 bytes_expected = AAC_INPUTBUF_SIZE - IOBuf->bytesLeft;
289
290 while (bytes_expected < 0) {
291 printk("bytes_expected = %d\n", bytes_expected);
292 }
293
294 if (bytes_expected > buf_level) {
295 bytes_expected = buf_level;
296 }
297
298 read_bytes = read_buffer(IOBuf->readBuf + IOBuf->bytesLeft, bytes_expected);
299
300 IOBuf->readPtr = IOBuf->readBuf;
301 IOBuf->bytesLeft += read_bytes;
302 } while (0);
303 if (IOBuf->bytesLeft < get_frame_size()) {
304 goto start_read;
305 }
306}
307
308static int aac_reset_decoder(HAACDecoder hAACDecoder, HAACIOBuf hIOBuf)
309{
310 AACIOBuf *IOBuf = (AACIOBuf*)hIOBuf;
311 IOBuf->readPtr = IOBuf->readBuf;
312 IOBuf->bytesLeft = 0;
313 return AACFlushCodec(hAACDecoder);
314}
315static int aac_decode_frame(HAACDecoder hAACDecoder, HAACIOBuf hIOBuf)
316{
317 int err;
318 AACIOBuf *IOBuf = (AACIOBuf*)hIOBuf;
319 if (AACDataSource == 1) {
320 if (IOBuf->bytesLeft < AAC_INPUTBUF_SIZE / 2) {
321 aac_refill_buffer(IOBuf);
322 }
323 }
324 if (exit_flag) {
325 return ERR_AAC_EXIT_DECODE;
326 }
327 /* decode one AAC frame */
328 err = AACDecode(hAACDecoder, &(IOBuf->readPtr), &(IOBuf->bytesLeft), (IOBuf->outBuf));
329 return err;
330}
331int audio_dec_init(audio_decoder_operations_t *adp)
332{
333 //printk("\n\n[%s]WFDAAC DEC BuildDate--%s BuildTime--%s", __FUNCTION__, __DATE__, __TIME__);
334 char value[PROPERTY_VALUE_MAX];
335 if (property_get("media.wfd.debug_dec", value, NULL) > 0) {
336 enable_debug_print = atoi(value);
337 }
338 int err = 0, ch = 0, i;
339 AACFrameInfo aacFrameInfo = {0};
340 audio_codec_print("helix_aac_decoder_init start \n");
341 err = uio_init();
342 if (err) {
343 return -1;
344 }
345 hAACDecoder = aac_init_decoder();
346 if (!hAACDecoder) {
347 printk("fatal error,helix aac decoder init failed\n");
348 return -1;
349 }
350 hAACIOBuf = aac_init_iobuf();
351 if (!hAACIOBuf) {
352 printk("fatal error,helix aac decoder init iobuf failed\n");
353
354 return -1;
355 }
356
357 return 0;
358}
359
360/*
361 channel configuration mapping
362 ch nums position
363 3 FC FL FR
364 4 FC FL FR BC
365 5 FC FL FR BL BR
366 6 FC FL FR BL BR LFE
367
368*/
369#define FATAL_ERR_RESET_COUNT 2000
370int audio_dec_decode(audio_decoder_operations_t *adec_ops, char *buf, int *outlen, char *inbuf, int inlen)
371{
372 int err, i, sample_out = 0, ch;
373 short *pcmbuf = (short*)buf;
374 short *ouput = (short*)(((AACIOBuf*)hAACIOBuf)->outBuf);
375 int ch_num;
376 int sum;
377 unsigned ch_map_scale[6] = {2, 4, 4, 2, 2, 0}; //full scale == 8
378 AACFrameInfo aacFrameInfo = {0};
379
380 err = aac_decode_frame(hAACDecoder, hAACIOBuf);
381 if (!err) {
382 error_count = 0;
383 AACGetLastFrameInfo(hAACDecoder, &aacFrameInfo);
384
385
386 /* L = (l+c)/2;R = (r+c)/2 */
387 if (aacFrameInfo.nChans > 2) { //should do downmix to 2ch output.
388 ch_num = aacFrameInfo.nChans;
389 sample_out = aacFrameInfo.outputSamps / ch_num * 2 * 2; //ch_num*sample_num*16bit
390 if (ch_num == 3 || ch_num == 4) {
391 ch_map_scale[0] = 4; //50%
392 ch_map_scale[1] = 4;//50%
393 ch_map_scale[2] = 4;//50%
394 ch_map_scale[3] = 0;
395 ch_map_scale[4] = 0;
396 ch_map_scale[5] = 0;
397 }
398 for (i = 0; i < aacFrameInfo.outputSamps / ch_num; i++) {
399 sum = ((int)ouput[ch_num * i + FRONT_LEFT] * ch_map_scale[FRONT_LEFT] + (int)ouput[ch_num * i + FRONT_CENTER] * ch_map_scale[FRONT_CENTER] + (int)ouput[ch_num * i + BACK_LEFT] * ch_map_scale[BACK_LEFT]);
400 pcmbuf[i * 2] = sum >> 3;
401 sum = ((int)ouput[ch_num * i + FRONT_RIGHT] * ch_map_scale[FRONT_RIGHT] + (int)ouput[ch_num * i + FRONT_CENTER] * ch_map_scale[FRONT_CENTER] + (int)ouput[ch_num * i + BACK_LEFT] * ch_map_scale[BACK_LEFT]);
402 pcmbuf[2 * i + 1] = sum >> 3;
403 }
404 } else {
405 memcpy(pcmbuf, ouput, aacFrameInfo.outputSamps * 2);
406 sample_out = aacFrameInfo.outputSamps * 2; //ch_num*sample_num*16bit
407 }
408
409 AACGetDecoderInfo(hAACDecoder, &aacFrameInfo);
410 // fmt->total_byte_parsed = aacFrameInfo.total_byte_parsed;
411 // fmt->total_sample_decoded = aacFrameInfo.total_sample_decoded;
412 // fmt->format = aacFrameInfo.format;
413 // fmt->bps = aacFrameInfo.bitRate;
414
415 lastFrameLen = ((AACDecInfo*)hAACDecoder)->frame_length;
416 /* record the frame length into the history buffer */
417 for (i = 0; i < FRAME_RECORD_NUM - 1; i++) {
418 frame_length_his[i] = frame_length_his[i + 1];
419 }
420 frame_length_his[FRAME_RECORD_NUM - 1] = lastFrameLen;
421 unsigned abuf_level = get_audiobuf_level();
422 unsigned dec_cached = ((AACIOBuf*)hAACIOBuf)->bytesLeft;
423 unsigned in_latency_ms = get_audio_inbuf_latency(abuf_level + dec_cached);
424 if (enable_debug_print)
425 printk("sampRateCore %d,sampRateOut %d,last frame len %d,avarge frame size %d,decode out sample %d,buf level %d,decode cached %d,total level %d ;latency %d ms \n", \
426 aacFrameInfo.sampRateCore, aacFrameInfo.sampRateOut, \
427 lastFrameLen, get_frame_size(), sample_out, \
428 abuf_level, dec_cached, abuf_level + dec_cached, in_latency_ms);
429 memcpy(inbuf, &in_latency_ms, sizeof(in_latency_ms));
430 lastSampPerFrm = sample_out;
431 adec_ops->samplerate = aacFrameInfo.sampRateOut;
432 adec_ops->channels = aacFrameInfo.nChans > 2 ? 2 : aacFrameInfo.nChans;
433 } else if (err == ERR_AAC_INDATA_UNDERFLOW) {
434 aac_refill_buffer(hAACIOBuf);
435 }
436 /* why add this ????
437 else if (err==ERR_AAC_NCHANS_TOO_HIGH)
438 {
439 //maybe we meet zero frame
440 ((AACIOBuf*)hAACIOBuf)->bytesLeft =0;
441 sample_out =0;
442 }
443 */
444 else if (err == ERR_AAC_EXIT_DECODE) {
445 sample_out = 0;
446 } else {
447 int frame_length;
448 if (ERR_AAC_SSR_GAIN_NOT_ADDED != err) {
449 error_count++;
450 }
451 // error, disable output, reset decoder and flush io
452 if (/*!mute_frame_num*/(error_count % 20) == 1) { //only print the every 20 times error
453#if 0
454 printk("helix aac decoder error,err num :%d,try output 40 mute frames and skip err bitstream\n", err);
455 printk("frame_length = %d\n", get_frame_size());
456 printk("sames per frame: %d\n", lastSampPerFrm);
457#endif
458 }
459 if (error_count == FATAL_ERR_RESET_COUNT) { // send to player to reset the player
460 printk("decoder error count FATAL_ERR_RESET_COUNT %s\n", FATAL_ERR_RESET_COUNT);
461 // trans_err_code(DECODE_FATAL_ERR);
462 }
463 //aac_reset_decoder(hAACDecoder, hAACIOBuf);
464 // AACFlushCodec(hAACDecoder);
465 frame_length = get_frame_size() * 2 / 3/*((AACDecInfo*)hAACDecoder)->frame_length*/; //skip 2/3 of last frame size
466 if (AACDataSource) {
467 if (frame_length > 0) {
468 if (((AACIOBuf*)hAACIOBuf)->bytesLeft > frame_length) {
469 ((AACIOBuf*)hAACIOBuf)->bytesLeft -= frame_length;
470 ((AACIOBuf*)hAACIOBuf)->readPtr += frame_length;
471 // printk("skip1 %d bytes \n",frame_length);
472 } else {
473 // printk("skip2 %d bytes \n",((AACIOBuf*)hAACIOBuf)->bytesLeft);
474
475 ((AACIOBuf*)hAACIOBuf)->readPtr = ((AACIOBuf*)hAACIOBuf)->readBuf;
476 ((AACIOBuf*)hAACIOBuf)->bytesLeft = 0;
477
478 }
479 } else {
480 if (((AACIOBuf*)hAACIOBuf)->bytesLeft > 100) {
481 ((AACIOBuf*)hAACIOBuf)->bytesLeft -= 100;
482 ((AACIOBuf*)hAACIOBuf)->readPtr += 100;
483
484 // printk("skip3 %d bytes \n",100);
485 } else {
486 // printk("skip4 %d bytes \n",((AACIOBuf*)hAACIOBuf)->bytesLeft);
487
488 ((AACIOBuf*)hAACIOBuf)->readPtr = ((AACIOBuf*)hAACIOBuf)->readBuf;
489 ((AACIOBuf*)hAACIOBuf)->bytesLeft = 0;
490
491 }
492 }
493 }
494
495 sample_out = 0;//lastSampPerFrm/*fmt->channel_num*2*1024*/;
496 mute_pcm_bytes = mute_pcm_thread;
497 }
498 if (sample_out && mute_pcm_bytes > 0) {
499 memset(buf, 0, sample_out);
500 mute_pcm_bytes -= sample_out;
501 }
502 if (!err) {
503 mute_pcm_thread = 0;
504
505 }
506
507
508 *outlen = sample_out;
509 return stream_in_offset;
510}
511
512int audio_dec_release(audio_decoder_operations_t *adec_ops)
513{
514#if 0
515 if (hAACIOBuf) {
516 free(hAACIOBuf);
517 hAACIOBuf = NULL;
518 }
519 if (hAACDecoder) {
520 AACFreeDecoder(hAACDecoder);
521 hAACDecoder = NULL;
522 }
523#endif
524 if (fd_uio >= 0) {
525 close(fd_uio);
526 }
527 fd_uio = -1;
528 if (memmap != NULL && memmap != MAP_FAILED) {
529 munmap(memmap, phys_size);
530 }
531 printk("WFDAAC audio_dec_release done \n");
532 return 0;
533}
534int audio_dec_getinfo(audio_decoder_operations_t *adec_ops, void *pAudioInfo)
535{
536 return 0;
537}
538
539
540void audio_set_exit_flag()
541{
542 exit_flag = 1;
543 printk("adec decode exit flag set \n");
544}
545
546
547
548
549