blob: b4acc092f9940fd94bd5171f4392eb3018e49e47
1 | /* |
2 | ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding |
3 | ** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com |
4 | ** |
5 | ** This program is free software; you can redistribute it and/or modify |
6 | ** it under the terms of the GNU General Public License as published by |
7 | ** the Free Software Foundation; either version 2 of the License, or |
8 | ** (at your option) any later version. |
9 | ** |
10 | ** This program is distributed in the hope that it will be useful, |
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | ** GNU General Public License for more details. |
14 | ** |
15 | ** You should have received a copy of the GNU General Public License |
16 | ** along with this program; if not, write to the Free Software |
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 | ** |
19 | ** Any non-GPL usage of this software or parts of this software is strictly |
20 | ** forbidden. |
21 | ** |
22 | ** The "appropriate copyright message" mentioned in section 2c of the GPLv2 |
23 | ** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" |
24 | ** |
25 | ** Commercial non-GPL licensing of this software is possible. |
26 | ** For more info contact Nero AG through Mpeg4AAClicense@nero.com. |
27 | ** |
28 | ** $Id: main.c,v 1.85 2008/09/22 17:55:09 menno Exp $ |
29 | **/ |
30 | |
31 | #ifdef WIN32 |
32 | #define WIN32_LEAN_AND_MEAN |
33 | #include <windows.h> |
34 | #define off_t __int64 |
35 | #else |
36 | #include <time.h> |
37 | #endif |
38 | |
39 | #include "libaacdec.h" |
40 | #include <stdio.h> |
41 | #include <stdarg.h> |
42 | #include <string.h> |
43 | #include <sys/time.h> |
44 | #ifndef WIN32 |
45 | #include <android/log.h> |
46 | #endif |
47 | |
48 | #define min(a,b) ( (a) < (b) ? (a) : (b) ) |
49 | |
50 | /* MicroSoft channel definitions */ |
51 | #define SPEAKER_FRONT_LEFT 0x1 |
52 | #define SPEAKER_FRONT_RIGHT 0x2 |
53 | #define SPEAKER_FRONT_CENTER 0x4 |
54 | #define SPEAKER_LOW_FREQUENCY 0x8 |
55 | #define SPEAKER_BACK_LEFT 0x10 |
56 | #define SPEAKER_BACK_RIGHT 0x20 |
57 | #define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 |
58 | #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 |
59 | #define SPEAKER_BACK_CENTER 0x100 |
60 | #define SPEAKER_SIDE_LEFT 0x200 |
61 | #define SPEAKER_SIDE_RIGHT 0x400 |
62 | #define SPEAKER_TOP_CENTER 0x800 |
63 | #define SPEAKER_TOP_FRONT_LEFT 0x1000 |
64 | #define SPEAKER_TOP_FRONT_CENTER 0x2000 |
65 | #define SPEAKER_TOP_FRONT_RIGHT 0x4000 |
66 | #define SPEAKER_TOP_BACK_LEFT 0x8000 |
67 | #define SPEAKER_TOP_BACK_CENTER 0x10000 |
68 | #define SPEAKER_TOP_BACK_RIGHT 0x20000 |
69 | #define SPEAKER_RESERVED 0x80000000 |
70 | |
71 | #define DefaultReadSize 1024*10 //read count from kernel audio buf one time |
72 | #define DefaultOutBufSize 1024*1024 |
73 | #define MAX_CHANNELS 6 /* make this higher to support files with more channels */ |
74 | |
75 | //audio decoder buffer 6144 bytes |
76 | #define AAC_INPUTBUF_SIZE 768 /* pick something big enough to hold a bunch of frames */ |
77 | |
78 | #define ERROR_RESET_COUNT 40 |
79 | #define RSYNC_SKIP_BYTES 1 |
80 | #define FRAME_RECORD_NUM 40 |
81 | #define FRAME_SIZE_MARGIN 300 |
82 | |
83 | enum { |
84 | AAC_ERROR_NO_ENOUGH_DATA = -1, |
85 | AAC_ERROR_NEED_RESET_DECODER = -2, |
86 | }; |
87 | |
88 | |
89 | typedef struct FaadContext { |
90 | NeAACDecHandle hDecoder; |
91 | int init_flag; |
92 | int header_type; |
93 | int gSampleRate; |
94 | int gChannels; |
95 | int error_count; |
96 | int frame_length_his[FRAME_RECORD_NUM]; |
97 | unsigned int muted_samples; |
98 | unsigned int muted_count; |
99 | unsigned init_cost; // summary init funciton cost bytes |
100 | unsigned init_start_flag; //start flag to summary data cost |
101 | int64_t starttime; |
102 | int64_t endtime; |
103 | } FaadContext; |
104 | |
105 | typedef(*findsyncfunc)(unsigned char *buf, int nBytes); |
106 | static const int adts_sample_rates[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0}; |
107 | |
108 | static int64_t gettime(void) |
109 | { |
110 | struct timeval tv; |
111 | gettimeofday(&tv, NULL); |
112 | return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; |
113 | } |
114 | |
115 | static long aacChannelConfig2wavexChannelMask(NeAACDecFrameInfo *hInfo) |
116 | { |
117 | if (hInfo->channels == 6 && hInfo->num_lfe_channels) { |
118 | return SPEAKER_FRONT_LEFT + SPEAKER_FRONT_RIGHT + |
119 | SPEAKER_FRONT_CENTER + SPEAKER_LOW_FREQUENCY + |
120 | SPEAKER_BACK_LEFT + SPEAKER_BACK_RIGHT; |
121 | } else { |
122 | return 0; |
123 | } |
124 | } |
125 | |
126 | static char *position2string(int position) |
127 | { |
128 | switch (position) { |
129 | case FRONT_CHANNEL_CENTER: |
130 | return "Center front"; |
131 | case FRONT_CHANNEL_LEFT: |
132 | return "Left front"; |
133 | case FRONT_CHANNEL_RIGHT: |
134 | return "Right front"; |
135 | case SIDE_CHANNEL_LEFT: |
136 | return "Left side"; |
137 | case SIDE_CHANNEL_RIGHT: |
138 | return "Right side"; |
139 | case BACK_CHANNEL_LEFT: |
140 | return "Left back"; |
141 | case BACK_CHANNEL_RIGHT: |
142 | return "Right back"; |
143 | case BACK_CHANNEL_CENTER: |
144 | return "Center back"; |
145 | case LFE_CHANNEL: |
146 | return "LFE"; |
147 | case UNKNOWN_CHANNEL: |
148 | return "Unknown"; |
149 | default: |
150 | return ""; |
151 | } |
152 | |
153 | return ""; |
154 | } |
155 | |
156 | |
157 | |
158 | static int FindAdtsSRIndex(int sr) |
159 | { |
160 | int i; |
161 | |
162 | for (i = 0; i < 16; i++) { |
163 | if (sr == adts_sample_rates[i]) { |
164 | return i; |
165 | } |
166 | } |
167 | return 16 - 1; |
168 | } |
169 | |
170 | static unsigned char *MakeAdtsHeader(int *dataSize, NeAACDecFrameInfo *hInfo, int old_format) |
171 | { |
172 | unsigned char *data; |
173 | int profile = (hInfo->object_type - 1) & 0x3; |
174 | int sr_index = ((hInfo->sbr == SBR_UPSAMPLED) || (hInfo->sbr == NO_SBR_UPSAMPLED)) ? |
175 | FindAdtsSRIndex(hInfo->samplerate / 2) : FindAdtsSRIndex(hInfo->samplerate); |
176 | int skip = (old_format) ? 8 : 7; |
177 | int framesize = skip + hInfo->bytesconsumed; |
178 | |
179 | if (hInfo->header_type == ADTS) { |
180 | framesize -= skip; |
181 | } |
182 | |
183 | *dataSize = 7; |
184 | |
185 | data = malloc(*dataSize * sizeof(unsigned char)); |
186 | memset(data, 0, *dataSize * sizeof(unsigned char)); |
187 | |
188 | data[0] += 0xFF; /* 8b: syncword */ |
189 | |
190 | data[1] += 0xF0; /* 4b: syncword */ |
191 | /* 1b: mpeg id = 0 */ |
192 | /* 2b: layer = 0 */ |
193 | data[1] += 1; /* 1b: protection absent */ |
194 | |
195 | data[2] += ((profile << 6) & 0xC0); /* 2b: profile */ |
196 | data[2] += ((sr_index << 2) & 0x3C); /* 4b: sampling_frequency_index */ |
197 | /* 1b: private = 0 */ |
198 | data[2] += ((hInfo->channels >> 2) & 0x1); /* 1b: channel_configuration */ |
199 | |
200 | data[3] += ((hInfo->channels << 6) & 0xC0); /* 2b: channel_configuration */ |
201 | /* 1b: original */ |
202 | /* 1b: home */ |
203 | /* 1b: copyright_id */ |
204 | /* 1b: copyright_id_start */ |
205 | data[3] += ((framesize >> 11) & 0x3); /* 2b: aac_frame_length */ |
206 | |
207 | data[4] += ((framesize >> 3) & 0xFF); /* 8b: aac_frame_length */ |
208 | |
209 | data[5] += ((framesize << 5) & 0xE0); /* 3b: aac_frame_length */ |
210 | data[5] += ((0x7FF >> 6) & 0x1F); /* 5b: adts_buffer_fullness */ |
211 | |
212 | data[6] += ((0x7FF << 2) & 0x3F); /* 6b: adts_buffer_fullness */ |
213 | /* 2b: num_raw_data_blocks */ |
214 | |
215 | return data; |
216 | } |
217 | |
218 | static unsigned get_frame_size(FaadContext *gFaadCxt) |
219 | { |
220 | int i; |
221 | unsigned sum = 0; |
222 | unsigned valid_his_num = 0; |
223 | for (i = 0; i < FRAME_RECORD_NUM; i++) { |
224 | if (gFaadCxt->frame_length_his[i] > 0) { |
225 | valid_his_num ++; |
226 | sum += gFaadCxt->frame_length_his[i]; |
227 | } |
228 | } |
229 | |
230 | if (valid_his_num == 0) { |
231 | return 2048; |
232 | } |
233 | |
234 | return sum / valid_his_num; |
235 | } |
236 | static void store_frame_size(FaadContext *gFaadCxt, int lastFrameLen) |
237 | { |
238 | /* record the frame length into the history buffer */ |
239 | int i = 0; |
240 | for (i = 0; i < FRAME_RECORD_NUM - 1; i++) { |
241 | gFaadCxt->frame_length_his[i] = gFaadCxt->frame_length_his[i + 1]; |
242 | } |
243 | gFaadCxt->frame_length_his[FRAME_RECORD_NUM - 1] = lastFrameLen; |
244 | } |
245 | |
246 | static int AACFindADTSSyncWord(unsigned char *buf, int nBytes) |
247 | { |
248 | int i; |
249 | for (i = 0; i < nBytes - 1; i++) { |
250 | if (((buf[i + 0] & 0xff) == 0xff) && ((buf[i + 1] & 0xf6) == 0xf0)) { |
251 | break; |
252 | } |
253 | } |
254 | return i; |
255 | } |
256 | //check two latm frames sync header |
257 | static int AACFindLATMSyncWord(unsigned char *buffer, int nBytes) |
258 | { |
259 | int i; |
260 | int i_frame_size = 0; |
261 | for (i = 0; i < nBytes - 2; i++) { |
262 | if (buffer[i] == 0x56 && (buffer[i + 1] & 0xe0) == 0xe0) { |
263 | i_frame_size = ((buffer[i + 1] & 0x1f) << 8) + buffer[i + 2]; |
264 | if (i_frame_size > 4608) { |
265 | audio_codec_print("i_frame_size exceed 4608 ,%d \n", i_frame_size); |
266 | } |
267 | if (i_frame_size > 0 && i_frame_size < 4608) { |
268 | break; |
269 | } |
270 | } |
271 | } |
272 | return i; |
273 | } |
274 | int audio_dec_init( |
275 | #ifndef WIN32 |
276 | audio_decoder_operations_t *adec_ops |
277 | #endif |
278 | ) |
279 | { |
280 | //audio_codec_print("[%s]BuildDate--%s BuildTime--%s", __FUNCTION__, __DATE__, __TIME__); |
281 | FaadContext *gFaadCxt = NULL; |
282 | adec_ops->pdecoder = calloc(1, sizeof(FaadContext)); |
283 | if (!adec_ops->pdecoder) { |
284 | audio_codec_print("malloc for decoder instance failed\n"); |
285 | return -1; |
286 | } |
287 | gFaadCxt = (FaadContext*)adec_ops->pdecoder; |
288 | memset(gFaadCxt, 0, sizeof(FaadContext)); |
289 | adec_ops->nInBufSize = AAC_INPUTBUF_SIZE; //4608 bytes input buffer size |
290 | adec_ops->nOutBufSize = 64 * 1024; //3 * adec_ops->channels * adec_ops->samplerate * 16/8; // 3s |
291 | gFaadCxt->gChannels = adec_ops->channels; |
292 | gFaadCxt->gSampleRate = adec_ops->samplerate; |
293 | gFaadCxt->init_flag = 0; |
294 | gFaadCxt->header_type = 1; //default adts |
295 | return 0; |
296 | } |
297 | static int audio_decoder_init( |
298 | #ifndef WIN32 |
299 | audio_decoder_operations_t *adec_ops, |
300 | #endif |
301 | char *outbuf, int *outlen, char *inbuf, int inlen, long *inbuf_consumed) |
302 | { |
303 | unsigned long samplerate; |
304 | unsigned char channels; |
305 | int ret; |
306 | NeAACDecConfigurationPtr config = NULL; |
307 | char *in_buf; |
308 | int inbuf_size; |
309 | in_buf = inbuf; |
310 | inbuf_size = inlen; |
311 | int nReadLen = 0; |
312 | FaadContext *gFaadCxt = (FaadContext*)adec_ops->pdecoder; |
313 | int islatm = 0; |
314 | if (!in_buf || !inbuf_size || !outbuf) { |
315 | audio_codec_print(" input/output buffer null or input len is 0 \n"); |
316 | } |
317 | retry: |
318 | //fixed to LATM aac frame header sync to speed up seek speed |
319 | #if 1 |
320 | if (adec_ops->nAudioDecoderType == ACODEC_FMT_AAC_LATM) { |
321 | islatm = 1; |
322 | int nSeekNum = AACFindLATMSyncWord(in_buf, inbuf_size); |
323 | if (nSeekNum == (inbuf_size - 2)) { |
324 | audio_codec_print("[%s %d]%d bytes data not found latm sync header \n", __FUNCTION__,__LINE__, nSeekNum); |
325 | } else { |
326 | audio_codec_print("[%s %d]latm seek sync header cost %d,total %d,left %d \n", __FUNCTION__,__LINE__, nSeekNum, inbuf_size, inbuf_size - nSeekNum); |
327 | } |
328 | inbuf_size = inbuf_size - nSeekNum; |
329 | if (inbuf_size < (get_frame_size(gFaadCxt) + FRAME_SIZE_MARGIN)/*AAC_INPUTBUF_SIZE/2*/) { |
330 | audio_codec_print("[%s %d]input size %d at least %d ,need more data \n", __FUNCTION__,__LINE__, inbuf_size, (get_frame_size(gFaadCxt) + FRAME_SIZE_MARGIN)); |
331 | *inbuf_consumed = inlen - inbuf_size; |
332 | return AAC_ERROR_NO_ENOUGH_DATA; |
333 | } |
334 | } |
335 | #endif |
336 | gFaadCxt->hDecoder = NeAACDecOpen(); |
337 | config = NeAACDecGetCurrentConfiguration(gFaadCxt->hDecoder); |
338 | config->defObjectType = LC; |
339 | config->outputFormat = FAAD_FMT_16BIT; |
340 | config->downMatrix = 0x01; |
341 | config->useOldADTSFormat = 0; |
342 | //config->dontUpSampleImplicitSBR = 1; |
343 | NeAACDecSetConfiguration(gFaadCxt->hDecoder, config); |
344 | int skipbytes=RSYNC_SKIP_BYTES; |
345 | if ((ret = NeAACDecInit(gFaadCxt->hDecoder, in_buf, inbuf_size, &samplerate, &channels, islatm,&skipbytes)) < 0) { |
346 | in_buf += skipbytes; |
347 | inbuf_size -= skipbytes; |
348 | NeAACDecClose(gFaadCxt->hDecoder); |
349 | gFaadCxt->hDecoder = NULL; |
350 | if (inbuf_size < 0) { |
351 | inbuf_size = 0; |
352 | } |
353 | audio_codec_print("init fail,inbuf_size %d \n", inbuf_size); |
354 | |
355 | if (inbuf_size < (get_frame_size(gFaadCxt) + FRAME_SIZE_MARGIN) || skipbytes == 0) { |
356 | audio_codec_print("skipbytes/%d inbuf_size/%d get_frame_size()/%d ,need more data \n",skipbytes, inbuf_size, (get_frame_size(gFaadCxt) + FRAME_SIZE_MARGIN)); |
357 | *inbuf_consumed = inlen - inbuf_size; |
358 | return AAC_ERROR_NO_ENOUGH_DATA; |
359 | } |
360 | goto retry; |
361 | } |
362 | audio_codec_print("init sucess cost %d\n", ret); |
363 | in_buf += ret; |
364 | inbuf_size -= ret; |
365 | *inbuf_consumed = inlen - inbuf_size; |
366 | NeAACDecStruct* hDecoder = (NeAACDecStruct*)(gFaadCxt->hDecoder); |
367 | gFaadCxt->init_flag = 1; |
368 | gFaadCxt->gChannels = channels; |
369 | gFaadCxt->gSampleRate = samplerate; |
370 | audio_codec_print("[%s] Init OK adif_present :%d adts_present:%d latm_present:%d,sr %d,ch %d\n", __FUNCTION__, hDecoder->adif_header_present, hDecoder->adts_header_present, hDecoder->latm_header_present, samplerate, channels); |
371 | return 0; |
372 | } |
373 | int audio_dec_decode( |
374 | #ifndef WIN32 |
375 | audio_decoder_operations_t *adec_ops, |
376 | #endif |
377 | char *outbuf, int *outlen, char *inbuf, int inlen) |
378 | { |
379 | unsigned long samplerate; |
380 | unsigned char channels; |
381 | void *sample_buffer; |
382 | NeAACDecFrameInfo frameInfo; |
383 | int outmaxlen = 0; |
384 | char *dec_buf; |
385 | int dec_bufsize; |
386 | int inbuf_consumed = 0; |
387 | int ret = 0; |
388 | FaadContext *gFaadCxt = (FaadContext*)adec_ops->pdecoder; |
389 | dec_bufsize = inlen; |
390 | dec_buf = inbuf; |
391 | outmaxlen = *outlen ; |
392 | *outlen = 0; |
393 | if (!outbuf || !inbuf || !inlen) { |
394 | audio_codec_print("decoder parameter error,check \n"); |
395 | goto exit; |
396 | } |
397 | if (gFaadCxt->init_start_flag == 0) { |
398 | audio_codec_print("MyFaadDecoder init first in \n"); |
399 | gFaadCxt->starttime = gettime(); |
400 | gFaadCxt->init_start_flag = 1; |
401 | } |
402 | if (!gFaadCxt->init_flag) { |
403 | gFaadCxt->error_count = 0; |
404 | audio_codec_print("begin audio_decoder_init,buf size %d \n", dec_bufsize); |
405 | ret = audio_decoder_init(adec_ops, outbuf, outlen, dec_buf, dec_bufsize, &inbuf_consumed); |
406 | if (ret == AAC_ERROR_NO_ENOUGH_DATA) { |
407 | audio_codec_print("decoder buf size %d,cost %d byte input data ,but initiation failed.^_^ \n", inlen, inbuf_consumed); |
408 | dec_bufsize -= inbuf_consumed; |
409 | goto exit; |
410 | } |
411 | gFaadCxt->init_flag = 1; |
412 | dec_buf += inbuf_consumed; |
413 | dec_bufsize -= inbuf_consumed; |
414 | gFaadCxt->init_cost += inbuf_consumed; |
415 | gFaadCxt->endtime = gettime(); |
416 | audio_codec_print(" MyFaadDecoder decoder init finished total cost %d bytes,consumed time %lld ms \n", gFaadCxt->init_cost, (gFaadCxt->endtime - gFaadCxt->starttime) / 1000); |
417 | gFaadCxt->init_cost = 0; |
418 | if (dec_bufsize < 0) { |
419 | dec_bufsize = 0; |
420 | } |
421 | } |
422 | NeAACDecStruct* hDecoder = (NeAACDecStruct*)(gFaadCxt->hDecoder); |
423 | //TODO .fix to LATM aac decoder when ffmpeg parser return LATM aac type |
424 | #if 0 |
425 | if (adec_ops->nAudioDecoderType == ACODEC_FMT_AAC_LATM) { |
426 | hDecoder->latm_header_present = 1; |
427 | } |
428 | #endif |
429 | if (hDecoder->adts_header_present) { |
430 | int nSeekNum = AACFindADTSSyncWord(dec_buf, dec_bufsize); |
431 | if (nSeekNum == (dec_bufsize - 1)) { |
432 | audio_codec_print("%d bytes data not found adts sync header \n", nSeekNum); |
433 | } |
434 | dec_bufsize = dec_bufsize - nSeekNum; |
435 | if (dec_bufsize < (get_frame_size(gFaadCxt) + FRAME_SIZE_MARGIN)/*AAC_INPUTBUF_SIZE/2*/) { |
436 | goto exit; |
437 | } |
438 | } |
439 | if (hDecoder->latm_header_present) { |
440 | int nSeekNum = AACFindLATMSyncWord(dec_buf, dec_bufsize); |
441 | if (nSeekNum == (dec_bufsize - 2)) { |
442 | audio_codec_print("%d bytes data not found latm sync header \n", nSeekNum); |
443 | } |
444 | dec_bufsize = dec_bufsize - nSeekNum; |
445 | if (dec_bufsize < (get_frame_size(gFaadCxt) + FRAME_SIZE_MARGIN)/*AAC_INPUTBUF_SIZE/2*/) { |
446 | goto exit; |
447 | } |
448 | } |
449 | sample_buffer = NeAACDecDecode(gFaadCxt->hDecoder, &frameInfo, dec_buf, dec_bufsize); |
450 | dec_bufsize -= frameInfo.bytesconsumed; |
451 | if (frameInfo.channels < 0 || frameInfo.channels > 8) { |
452 | audio_codec_print("[%s %d]ERR__Unvalid Nch/%d bytesconsumed/%d error/%d\n", |
453 | __FUNCTION__,__LINE__,frameInfo.channels,frameInfo.bytesconsumed,frameInfo.error); |
454 | sample_buffer=NULL; |
455 | } |
456 | if (frameInfo.error == 0 && sample_buffer == NULL && hDecoder->latm_header_present) { |
457 | dec_bufsize -= 3; |
458 | goto exit; |
459 | } |
460 | if ((frameInfo.error == 0) && (frameInfo.samples > 0) && sample_buffer != NULL) { |
461 | store_frame_size(gFaadCxt, frameInfo.bytesconsumed); |
462 | gFaadCxt->gSampleRate = frameInfo.samplerate; |
463 | gFaadCxt->gChannels = frameInfo.channels; |
464 | //code to mute first 1 s ??? |
465 | #define MUTE_S 0.2 |
466 | if (gFaadCxt->muted_samples == 0) { |
467 | gFaadCxt->muted_samples = gFaadCxt->gSampleRate * gFaadCxt->gChannels * MUTE_S; |
468 | } |
469 | if (gFaadCxt->muted_count < gFaadCxt->muted_samples) { |
470 | memset(sample_buffer, 0, 2 * frameInfo.samples); |
471 | gFaadCxt->muted_count += frameInfo.samples; |
472 | } |
473 | if ((outmaxlen - (*outlen)) >= (2 * frameInfo.samples)) { |
474 | memcpy(outbuf + (*outlen), sample_buffer, 2 * frameInfo.samples); |
475 | *outlen += 2 * frameInfo.samples; |
476 | gFaadCxt->error_count = 0; |
477 | } else { |
478 | audio_codec_print("[%s %d]WARNING: no enough space used for pcm!\n", __FUNCTION__, __LINE__); |
479 | } |
480 | } |
481 | |
482 | if (frameInfo.error > 0) { //failed seek to the head |
483 | if (frameInfo.error != 34 && frameInfo.error != 35) { |
484 | dec_bufsize -= RSYNC_SKIP_BYTES; |
485 | audio_codec_print("Error: %s,inlen %d\n", NeAACDecGetErrorMessage(frameInfo.error), inlen); |
486 | } |
487 | // sr/ch changed info happened 5 times always,some times error maybe,skip bytes |
488 | else if (frameInfo.error == 34 && gFaadCxt->error_count > 5) { |
489 | dec_bufsize -= RSYNC_SKIP_BYTES; |
490 | audio_codec_print("%s,,inlen %d\n", NeAACDecGetErrorMessage(frameInfo.error), inlen); |
491 | } |
492 | gFaadCxt->error_count++; |
493 | //err 34,means aac profile changed , PS.SBR,LC ....,normally happens when switch audio source |
494 | if (gFaadCxt->error_count >= ERROR_RESET_COUNT || frameInfo.error == 34) { |
495 | if (gFaadCxt->hDecoder) { |
496 | NeAACDecClose(gFaadCxt->hDecoder); |
497 | gFaadCxt->hDecoder = NULL; |
498 | } |
499 | gFaadCxt->init_flag = 0; |
500 | gFaadCxt->init_start_flag = 0; |
501 | } |
502 | } |
503 | exit: |
504 | if (dec_bufsize < 0) { |
505 | dec_bufsize = 0; |
506 | } |
507 | if (gFaadCxt->init_flag == 0) { |
508 | gFaadCxt->init_cost += (inlen - dec_bufsize); |
509 | } |
510 | return inlen - dec_bufsize; |
511 | } |
512 | |
513 | |
514 | int audio_dec_release( |
515 | #ifndef WIN32 |
516 | audio_decoder_operations_t *adec_ops |
517 | #endif |
518 | ) |
519 | { |
520 | FaadContext *gFaadCxt = (FaadContext*)adec_ops->pdecoder; |
521 | if (gFaadCxt->hDecoder) { |
522 | NeAACDecClose(gFaadCxt->hDecoder); |
523 | } |
524 | if (adec_ops->pdecoder) { |
525 | free(adec_ops->pdecoder); |
526 | adec_ops->pdecoder = NULL; |
527 | } |
528 | return 0; |
529 | } |
530 | #ifndef WIN32 |
531 | int audio_dec_getinfo(audio_decoder_operations_t *adec_ops, void *pAudioInfo) |
532 | { |
533 | FaadContext *gFaadCxt = (FaadContext*)adec_ops->pdecoder; |
534 | NeAACDecStruct* hDecoder = (NeAACDecStruct*)gFaadCxt->hDecoder; |
535 | adec_ops->NchOriginal = hDecoder->fr_channels; |
536 | ((AudioInfo *)pAudioInfo)->channels = gFaadCxt->gChannels; |
537 | ((AudioInfo *)pAudioInfo)->samplerate = gFaadCxt->gSampleRate; |
538 | return 0; |
539 | } |
540 | #endif |
541 | |
542 | |
543 | |
544 | |
545 |