1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 /************************************************************************** |
|
21 aacaud.cpp - High level interface implementations for AAC decoder. |
|
22 |
|
23 Author(s): Juha Ojanpera |
|
24 Copyright (c) 2000-2004 by Nokia Research Center, Speech and Audio Systems. |
|
25 *************************************************************************/ |
|
26 |
|
27 /*-- System Headers. --*/ |
|
28 #include <math.h> |
|
29 |
|
30 /*-- Project Headers. --*/ |
|
31 #include "aacaud.h" |
|
32 #include "dec_huf.h" |
|
33 #include "tool2.h" |
|
34 |
|
35 CAACAudDec* CAACAudDec::NewL(int16 aNumCh, int16 aNumCCh) |
|
36 { |
|
37 CAACAudDec* self = new (ELeave) CAACAudDec(); |
|
38 CleanupStack::PushL(self); |
|
39 self->ConstructL(aNumCh, aNumCCh); |
|
40 CleanupStack::Pop(self); |
|
41 return self; |
|
42 } |
|
43 |
|
44 void CAACAudDec::ConstructL(int16 aNumCh, int16 aNumCCh) |
|
45 { |
|
46 |
|
47 //-----------------> |
|
48 |
|
49 int16 i, tmp; |
|
50 |
|
51 numCh = aNumCh; |
|
52 numCCh = aNumCCh; |
|
53 |
|
54 /*-- Set the limit for the number of decoded audio elements. --*/ |
|
55 if(numCh > ChansD - XChansD) |
|
56 numCh = ChansD - XChansD; |
|
57 |
|
58 /*-- How many coupling channels are accepted ? --*/ |
|
59 if(numCCh > CChansD - XCChansD) |
|
60 numCCh = CChansD - XCChansD; |
|
61 |
|
62 /*-- # of channels outputted. --*/ |
|
63 numOutCh = numCh; |
|
64 |
|
65 /*-- Allocate main channel elements. --*/ |
|
66 tmp = (int16) (numCh + XChansD); |
|
67 |
|
68 winInfo = new (ELeave) CWindowInfo*[tmp]; |
|
69 tool = new (ELeave) CToolInfo*[tmp]; |
|
70 |
|
71 windowAmount = tmp; |
|
72 |
|
73 for(i = 0; i < tmp; i++) |
|
74 { |
|
75 winInfo[i] = CWindowInfo::NewL(); |
|
76 tool[i] = CToolInfo::NewL(); |
|
77 } |
|
78 |
|
79 /*-- Allocate coupling channel elements. --*/ |
|
80 tmp = (int16) (numCCh + XCChansD); |
|
81 ccInfo = new (ELeave) CCInfo*[tmp]; |
|
82 |
|
83 for(i = 0; i < tmp; i++) |
|
84 { |
|
85 ccInfo[i] = CCInfo::NewL(); |
|
86 } |
|
87 |
|
88 /*-- Get spectral codebooks parameters. --*/ |
|
89 huf = LoadHuffmanDecTablesL(); |
|
90 |
|
91 /*-- Get scalefactor codebook parameters. --*/ |
|
92 sf_huf = LoadSfHuffmanTableL(); |
|
93 |
|
94 mc_info = CMC_Info::NewL(); |
|
95 |
|
96 for(i = 0; i < ChansD; i++) |
|
97 { |
|
98 mc_info->ch_info[i].huf = huf; |
|
99 mc_info->ch_info[i].sf_huf = sf_huf; |
|
100 } |
|
101 |
|
102 //<------------------ |
|
103 |
|
104 } |
|
105 |
|
106 CAACAudDec::CAACAudDec() : tool(0), mc_info(0), ccInfo(0), winInfo(0), |
|
107 huf(0), sf_huf(0) |
|
108 { |
|
109 #ifdef EAACPLUS_DECODER |
|
110 sbrStream = NULL; |
|
111 sbrDecInfo = NULL; |
|
112 #endif /*-- EAACPLUS_DECODER --*/ |
|
113 } |
|
114 |
|
115 CAACAudDec::~CAACAudDec() |
|
116 { |
|
117 |
|
118 /*-- Allocate main channel elements. --*/ |
|
119 TInt tmp = (int16) (numCh + XChansD); |
|
120 TInt i = 0; |
|
121 if (winInfo != 0) |
|
122 { |
|
123 for(i = 0; i < tmp; i++) |
|
124 { |
|
125 if (winInfo[i] != 0) delete winInfo[i]; |
|
126 if (tool[i] != 0) delete tool[i]; |
|
127 } |
|
128 |
|
129 delete[] winInfo; |
|
130 } |
|
131 |
|
132 if (tool != 0) delete[] tool; |
|
133 |
|
134 |
|
135 /*-- Allocate coupling channel elements. --*/ |
|
136 tmp = (int16) (numCCh + XCChansD); |
|
137 |
|
138 if (ccInfo != 0) |
|
139 { |
|
140 for(i = 0; i < tmp; i++) |
|
141 { |
|
142 if (ccInfo[i] != 0) delete ccInfo[i]; |
|
143 } |
|
144 } |
|
145 |
|
146 if (ccInfo != 0) delete[] ccInfo; |
|
147 |
|
148 CloseHuffmanDecTables(huf); huf = NULL; |
|
149 CloseSfHuffmanTable(sf_huf); sf_huf = NULL; |
|
150 |
|
151 if (mc_info != 0) delete mc_info; |
|
152 |
|
153 |
|
154 sbrStream = CloseSBRBitStream(sbrStream); |
|
155 sbrDecInfo = CloseSBR(sbrDecInfo); |
|
156 |
|
157 } |
|
158 |
|
159 /* |
|
160 * Prepares Ch_Info structure for given audio element. The return value is |
|
161 * channel index into 'mip->ch_into' structure. |
|
162 */ |
|
163 static INLINE int16 |
|
164 enter_chn(int16 nch, int16 tag, int16 common_window, CMC_Info *mip) |
|
165 { |
|
166 TCh_Info *cip; |
|
167 BOOL parseCh; |
|
168 int16 cidx = 0; |
|
169 |
|
170 /*-- Build configuration. --*/ |
|
171 if(mip->nch + nch > (mip->maxnCh + 1) || mip->dummyAlways) |
|
172 { |
|
173 parseCh = FALSE; |
|
174 cidx = mip->dummyCh; |
|
175 mip->dummyAlways = TRUE; |
|
176 } |
|
177 else |
|
178 { |
|
179 parseCh = TRUE; |
|
180 cidx = mip->nch; |
|
181 mip->nch = (int16) (mip->nch + nch); |
|
182 } |
|
183 |
|
184 if(nch == 1) /*-- SCE. --*/ |
|
185 { |
|
186 cip = &mip->ch_info[cidx]; |
|
187 |
|
188 cip->cpe = 0; |
|
189 cip->ncch = 0; |
|
190 cip->tag = tag; |
|
191 cip->widx = cidx; |
|
192 cip->present = 1; |
|
193 cip->paired_ch = cidx; |
|
194 cip->parseCh = parseCh; |
|
195 } |
|
196 else /*-- CPE. --*/ |
|
197 { |
|
198 /*-- Left. --*/ |
|
199 cip = &mip->ch_info[cidx]; |
|
200 cip->cpe = 1; |
|
201 cip->ncch = 0; |
|
202 cip->tag = tag; |
|
203 cip->widx = cidx; |
|
204 cip->present = 1; |
|
205 cip->parseCh = parseCh; |
|
206 cip->paired_ch = (int16) (cidx + 1); |
|
207 |
|
208 /*-- Right. ---*/ |
|
209 cip = &mip->ch_info[cidx + 1]; |
|
210 cip->cpe = 1; |
|
211 cip->ncch = 0; |
|
212 cip->tag = tag; |
|
213 cip->present = 1; |
|
214 cip->paired_ch = cidx; |
|
215 cip->parseCh = parseCh; |
|
216 cip->widx = (common_window) ? (int16) cidx : (int16) (cidx + 1); |
|
217 } |
|
218 |
|
219 return (cidx); |
|
220 } |
|
221 |
|
222 /* |
|
223 * Retrieve appropriate channel index for the program and decoder configuration. |
|
224 */ |
|
225 int16 |
|
226 ChIndex(int16 nch, int16 tag, int16 wnd, CMC_Info *mip) |
|
227 { |
|
228 /* |
|
229 * Channel index to position mapping for 5.1 configuration is : |
|
230 * 0 center |
|
231 * 1 left front |
|
232 * 2 right front |
|
233 * 3 left surround |
|
234 * 4 right surround |
|
235 * 5 lfe |
|
236 */ |
|
237 return (enter_chn(nch, tag, wnd, mip)); |
|
238 } |
|
239 |
|
240 /* |
|
241 * Given cpe and tag, returns channel index of SCE or left channel in CPE. |
|
242 */ |
|
243 int16 |
|
244 CCChIndex(CMC_Info *mip, int16 cpe, int16 tag) |
|
245 { |
|
246 int16 ch; |
|
247 TCh_Info *cip = &mip->ch_info[0]; |
|
248 |
|
249 for(ch = 0; ch < mip->nch; ch++, cip++) |
|
250 if(cip->cpe == cpe && cip->tag == tag) |
|
251 return (ch); |
|
252 |
|
253 /* |
|
254 * No match, so channel is not in this program. Just parse the channel(s). |
|
255 */ |
|
256 cip = &mip->ch_info[mip->dummyCh]; |
|
257 cip->cpe = cpe; |
|
258 cip->widx = mip->dummyCh; |
|
259 cip->parseCh = TRUE; |
|
260 |
|
261 return (mip->dummyCh); |
|
262 } |
|
263 |
|
264 /* |
|
265 * Checks continuity of configuration from one block to next. |
|
266 */ |
|
267 static INLINE void |
|
268 ResetMCInfo(CMC_Info *mip) |
|
269 { |
|
270 /*-- Reset channels counts. --*/ |
|
271 mip->nch = 0; |
|
272 mip->ncch = 0; |
|
273 mip->dummyAlways = 0; |
|
274 } |
|
275 |
|
276 /* |
|
277 * Deletes resources allocated to the specified AAC decoder. |
|
278 */ |
|
279 EXPORT_C CAACAudDec * |
|
280 DeleteAACAudDec(CAACAudDec *aac) |
|
281 { |
|
282 if(aac) |
|
283 { |
|
284 delete (aac); |
|
285 aac = 0; |
|
286 } |
|
287 |
|
288 return (NULL); |
|
289 } |
|
290 |
|
291 /* |
|
292 * Creates handle to AAC decoder core. The input parameters are |
|
293 * the number of main ('numCh') and coupling ('numCCh') channels |
|
294 * to be supported. |
|
295 * |
|
296 * Return AAC decoder handle on success, NULL on failure. |
|
297 */ |
|
298 EXPORT_C void |
|
299 CreateAACAudDecL(CAACAudDec*& aDecHandle, int16 numCh, int16 numCCh) |
|
300 { |
|
301 aDecHandle = CAACAudDec::NewL(numCh, numCCh); |
|
302 |
|
303 return; |
|
304 } |
|
305 |
|
306 /* |
|
307 * Creates handle to eAAC+ decoder. |
|
308 */ |
|
309 EXPORT_C uint8 |
|
310 CreateAACPlusAudDecL(CAACAudDec *aDecHandle, int16 sampleRateIdx, uint8 isStereo, uint8 isDualMono) |
|
311 { |
|
312 |
|
313 int32 sampleRate = AACSampleRate(sampleRateIdx); |
|
314 |
|
315 aDecHandle->sbrStream = OpenSBRBitStreamL(); |
|
316 aDecHandle->sbrDecInfo = OpenSBRDecoderL(sampleRate, 1024, isStereo, isDualMono); |
|
317 |
|
318 return (1); |
|
319 |
|
320 |
|
321 } |
|
322 |
|
323 /* |
|
324 * Prepares AAC core engine for decoding. The input parameters are the |
|
325 * AAC profile ID (or object type in case MPEG-4 AAC) and the sampling |
|
326 * rate index. |
|
327 */ |
|
328 EXPORT_C void |
|
329 InitAACAudDec(CAACAudDec *aac, int16 profile, int16 sampleRateIdx, uint8 is960) |
|
330 { |
|
331 int16 i, j; |
|
332 CMC_Info *mip; |
|
333 PredType predType; |
|
334 |
|
335 mip = aac->mc_info; |
|
336 |
|
337 mip->profile = (uint8) profile; |
|
338 mip->sfreq_idx = (uint8) sampleRateIdx; |
|
339 |
|
340 mip->cur_prog = -1; |
|
341 mip->default_config = 1; |
|
342 |
|
343 /* |
|
344 * Set channel restrictions so that we know how to handle |
|
345 * unused channel elements. |
|
346 */ |
|
347 mip->maxnCh = aac->numCh; |
|
348 mip->dummyCh = mip->maxnCh; |
|
349 mip->maxnCCh = aac->numCCh; |
|
350 mip->dummyCCh = mip->maxnCCh; |
|
351 |
|
352 /*-- Initialize sfb parameters. --*/ |
|
353 AACSfbInfoInit(mip->sfbInfo, mip->sfreq_idx, is960); |
|
354 |
|
355 ResetAACAudDec(aac); |
|
356 |
|
357 /*-- How many bands used for prediction (BWAP or LTP). --*/ |
|
358 if(profile == LTP_Object) |
|
359 { |
|
360 predType = LTP_PRED; |
|
361 j = LTP_MAX_PRED_BANDS; |
|
362 } |
|
363 else |
|
364 { |
|
365 j = 0; |
|
366 predType = NO_PRED; |
|
367 } |
|
368 |
|
369 for(i = 0; i < aac->numCh + XChansD; i++) |
|
370 { |
|
371 aac->winInfo[i]->predBands = (uint8) j; |
|
372 aac->winInfo[i]->predType = predType; |
|
373 } |
|
374 for(i = 0; i < aac->numCCh + XCChansD; i++) |
|
375 { |
|
376 aac->ccInfo[i]->winInfo->predBands = (uint8) j; |
|
377 aac->ccInfo[i]->winInfo->predType = predType; |
|
378 } |
|
379 |
|
380 aac->samplesPerFrame = (is960) ? (int16) LN2_960 : (int16) LN2; |
|
381 } |
|
382 |
|
383 /* |
|
384 * Resets internal members from the specified AAC decoder core. |
|
385 */ |
|
386 EXPORT_C void |
|
387 ResetAACAudDec(CAACAudDec *aac) |
|
388 { |
|
389 int16 i; |
|
390 CMC_Info *mip; |
|
391 CWindowInfo *winInfo; |
|
392 |
|
393 mip = aac->mc_info; |
|
394 |
|
395 /*-- Reset some modules. --*/ |
|
396 ResetMCInfo(mip); |
|
397 |
|
398 /* |
|
399 * Assume that the first window shape is of type Kaiser-Bessel |
|
400 * Derived (KBD). If not, then we use it anyway. The mismatch |
|
401 * in the first frame is not of prime importance. |
|
402 */ |
|
403 |
|
404 for(i = 0; i < aac->numCh; i++) |
|
405 { |
|
406 //tool = aac->tool[i]; |
|
407 winInfo = aac->winInfo[i]; |
|
408 |
|
409 winInfo->wshape[0].prev_bk = WS_KBD; |
|
410 winInfo->wshape[1].prev_bk = WS_KBD; |
|
411 } |
|
412 |
|
413 for(i = 0; i < aac->numCCh; i++) |
|
414 { |
|
415 //tool = aac->ccInfo[i]->tool; |
|
416 |
|
417 aac->ccInfo[i]->winInfo->wshape[0].prev_bk = WS_KBD; |
|
418 aac->ccInfo[i]->winInfo->wshape[1].prev_bk = WS_KBD; |
|
419 } |
|
420 } |
|
421 |
|
422 /* |
|
423 * Reads data stream element from the specified bitstream. |
|
424 * |
|
425 * Returns # of read bits. |
|
426 */ |
|
427 static INLINE int16 |
|
428 GetDSE(TBitStream *bs) |
|
429 { |
|
430 int16 align_flag, cnt, bitsRead; |
|
431 |
|
432 bitsRead = (int16) BsGetBitsRead(bs); |
|
433 |
|
434 // read tag |
|
435 BsGetBits(bs, LEN_TAG); |
|
436 align_flag = (int16) BsGetBits(bs, LEN_D_ALIGN); |
|
437 cnt = (int16) BsGetBits(bs, LEN_D_CNT); |
|
438 |
|
439 if(cnt == (1 << LEN_D_CNT) - 1) |
|
440 cnt = (int16) (cnt + BsGetBits(bs, LEN_D_ESC)); |
|
441 |
|
442 if(align_flag) BsByteAlign(bs); |
|
443 |
|
444 BsSkipNBits(bs, cnt << 3); |
|
445 |
|
446 bitsRead = (int16) (BsGetBitsRead(bs) - bitsRead); |
|
447 |
|
448 return (bitsRead); |
|
449 } |
|
450 |
|
451 /* |
|
452 * Reads fill element from the bitstream. |
|
453 */ |
|
454 int32 |
|
455 CAACAudDec::extension_payload(TBitStream *bs, int32 cnt, uint32 prevEleID) |
|
456 { |
|
457 uint8 extType = (uint8) BsGetBits(bs, LEN_EX_TYPE); |
|
458 |
|
459 switch(extType) |
|
460 { |
|
461 case EX_FILL_DATA: |
|
462 default: |
|
463 if(sbrStream && !ReadSBRExtensionData(bs, sbrStream, extType, prevEleID, cnt)) |
|
464 { |
|
465 |
|
466 BsGetBits(bs, LEN_NIBBLE); |
|
467 BsSkipNBits(bs, (cnt - 1) << 3); |
|
468 break; |
|
469 |
|
470 } |
|
471 else if (!sbrStream) |
|
472 { |
|
473 BsGetBits(bs, LEN_NIBBLE); |
|
474 BsSkipNBits(bs, (cnt - 1) << 3); |
|
475 break; |
|
476 |
|
477 } |
|
478 |
|
479 |
|
480 |
|
481 } |
|
482 |
|
483 return (cnt); |
|
484 } |
|
485 |
|
486 /* |
|
487 * Reads fill data from the bitstream. |
|
488 */ |
|
489 void |
|
490 CAACAudDec::GetFIL(TBitStream *bs, uint32 prevEleID) |
|
491 { |
|
492 int32 cnt; |
|
493 |
|
494 cnt = BsGetBits(bs, LEN_F_CNT); |
|
495 if(cnt == (1 << LEN_F_CNT) - 1) |
|
496 cnt += BsGetBits(bs, LEN_F_ESC) - 1; |
|
497 |
|
498 while(cnt > 0) |
|
499 cnt -= extension_payload(bs, cnt, prevEleID); |
|
500 } |
|
501 |
|
502 /* |
|
503 * Reads program configuration element from the specified bitstream. |
|
504 */ |
|
505 int16 |
|
506 GetPCE(TBitStream *bs, TProgConfig *p) |
|
507 { |
|
508 int16 i; |
|
509 |
|
510 p->pce_present = TRUE; |
|
511 p->tag = (int16) BsGetBits(bs, LEN_TAG); |
|
512 p->profile = (int16) BsGetBits(bs, LEN_PROFILE); |
|
513 p->sample_rate_idx = (int16) BsGetBits(bs, LEN_SAMP_IDX); |
|
514 p->front.num_ele = (int16) BsGetBits(bs, LEN_NUM_ELE); |
|
515 p->side.num_ele = (int16) BsGetBits(bs, LEN_NUM_ELE); |
|
516 p->back.num_ele = (int16) BsGetBits(bs, LEN_NUM_ELE); |
|
517 p->lfe.num_ele = (int16) BsGetBits(bs, LEN_NUM_LFE); |
|
518 p->data.num_ele = (int16) BsGetBits(bs, LEN_NUM_DAT); |
|
519 p->coupling.num_ele = (int16) BsGetBits(bs, LEN_NUM_CCE); |
|
520 |
|
521 p->mono_mix.present = (int16) BsGetBits(bs, 1); |
|
522 if(p->mono_mix.present == 1) |
|
523 p->mono_mix.ele_tag = (int16) BsGetBits(bs, LEN_TAG); |
|
524 |
|
525 p->stereo_mix.present = (int16) BsGetBits(bs, 1); |
|
526 if(p->stereo_mix.present == 1) |
|
527 p->stereo_mix.ele_tag = (int16) BsGetBits(bs, LEN_TAG); |
|
528 |
|
529 p->matrix_mix.present = (int16) BsGetBits(bs, 1); |
|
530 if(p->matrix_mix.present == 1) |
|
531 { |
|
532 p->matrix_mix.ele_tag = (int16) BsGetBits(bs, LEN_MMIX_IDX); |
|
533 p->matrix_mix.pseudo_enab = (int16) BsGetBits(bs, LEN_PSUR_ENAB); |
|
534 } |
|
535 |
|
536 for(i = 0; i < p->front.num_ele; i++) |
|
537 { |
|
538 p->front.ele_is_cpe[i] = (int16) BsGetBits(bs, LEN_ELE_IS_CPE); |
|
539 p->front.ele_tag[i] = (int16) BsGetBits(bs, LEN_TAG); |
|
540 } |
|
541 |
|
542 for(i = 0; i < p->side.num_ele; i++) |
|
543 { |
|
544 p->side.ele_is_cpe[i] = (int16) BsGetBits(bs, LEN_ELE_IS_CPE); |
|
545 p->side.ele_tag[i] = (int16) BsGetBits(bs, LEN_TAG); |
|
546 } |
|
547 |
|
548 for(i = 0; i < p->back.num_ele; i++) |
|
549 { |
|
550 p->back.ele_is_cpe[i] = (int16) BsGetBits(bs, LEN_ELE_IS_CPE); |
|
551 p->back.ele_tag[i] = (int16) BsGetBits(bs, LEN_TAG); |
|
552 } |
|
553 |
|
554 for(i = 0; i < p->lfe.num_ele; i++) |
|
555 { |
|
556 p->lfe.ele_is_cpe[i] = 0; |
|
557 p->lfe.ele_tag[i] = (int16) BsGetBits(bs, LEN_TAG); |
|
558 } |
|
559 |
|
560 for(i = 0; i < p->data.num_ele; i++) |
|
561 { |
|
562 p->data.ele_is_cpe[i] = 0; |
|
563 p->data.ele_tag[i] = (int16) BsGetBits(bs, LEN_TAG); |
|
564 } |
|
565 |
|
566 for(i = 0; i < p->coupling.num_ele; i++) |
|
567 { |
|
568 p->coupling.ele_is_cpe[i] = (int16) BsGetBits(bs, LEN_ELE_IS_CPE); |
|
569 p->coupling.ele_tag[i] = (int16) BsGetBits(bs, LEN_TAG); |
|
570 } |
|
571 |
|
572 BsByteAlign(bs); |
|
573 |
|
574 p->num_comment_bytes = (int16) BsGetBits(bs, LEN_COMMENT_BYTES); |
|
575 BsSkipNBits(bs, p->num_comment_bytes << 3); |
|
576 |
|
577 return (p->tag); |
|
578 } |
|
579 |
|
580 /** |
|
581 * Saves the start position of the channel element within the AAC frame. |
|
582 */ |
|
583 static void |
|
584 SaveSBRChannelElementPos(SbrBitStream *sbrStream, uint32 bitOffset, uint32 ele_id) |
|
585 { |
|
586 if(sbrStream->NrElements < MAX_NR_ELEMENTS) |
|
587 { |
|
588 /*-- Save starting position of the channel element. --*/ |
|
589 sbrStream->sbrElement[sbrStream->NrElements].elementOffset = bitOffset - 3; |
|
590 sbrStream->sbrElement[sbrStream->NrElements].ElementID = ele_id; |
|
591 } |
|
592 } |
|
593 |
|
594 /** |
|
595 * Saves the length of the channel element within the AAC frame. |
|
596 */ |
|
597 static void |
|
598 SaveSBRChannelElementLen(SbrBitStream *sbrStream, uint32 presentPos) |
|
599 { |
|
600 if(sbrStream->NrElements < MAX_NR_ELEMENTS) |
|
601 { |
|
602 /*-- Save length of the channel element. --*/ |
|
603 sbrStream->sbrElement[sbrStream->NrElements].chElementLen = |
|
604 presentPos - sbrStream->sbrElement[sbrStream->NrElements].elementOffset; |
|
605 } |
|
606 } |
|
607 /************************************************************************** |
|
608 Title : CountAACChunkLength |
|
609 |
|
610 Purpose : Counts the number of bytes reserved for the payload part of |
|
611 current AAC frame. This functions should only be called if |
|
612 no other methods exist to determine the payload legth |
|
613 (e.g., ADIF does not include this kind of information). |
|
614 |
|
615 Usage : y = CountAACChunkLength(bs, aac, bytesInFrame) |
|
616 |
|
617 Input : bs - input bitstream |
|
618 aac - AAC decoder parameters |
|
619 |
|
620 Output : y - status of operation |
|
621 bytesInFrame - # of bytes reserved for this frame |
|
622 |
|
623 Author(s) : Juha Ojanpera |
|
624 *************************************************************************/ |
|
625 |
|
626 EXPORT_C int16 |
|
627 CountAACChunkLength(TBitStream *bs, CAACAudDec *aac, int16 *bytesInFrame) |
|
628 { |
|
629 uint32 bitsRead; |
|
630 int16 frameStatus; |
|
631 |
|
632 /*-- Save the status of input bitstream. --*/ |
|
633 bitsRead = BsGetBitsRead(bs); |
|
634 |
|
635 /*-- Parse the frame. --*/ |
|
636 frameStatus = (!GetAACGlobalGains(bs, aac, 15, NULL, NULL)) ? (int16) 0 : (int16) 1; |
|
637 ResetMCInfo(aac->mc_info); |
|
638 |
|
639 /*-- Determine the # of bytes for this frame. --*/ |
|
640 bitsRead = BsGetBitsRead(bs) - bitsRead; |
|
641 *bytesInFrame = (int16) ((bitsRead >> 3) + ((bitsRead & 0x7) ? 1 : 0)); |
|
642 |
|
643 return (frameStatus); |
|
644 } |
|
645 |
|
646 /************************************************************************** |
|
647 Title : GetAACGlobalGains |
|
648 |
|
649 Purpose : Extracts 'global_gain' bitstream elements from the specified |
|
650 AAC data buffer. |
|
651 |
|
652 Usage : y = GetAACGlobalGains(bs, aac, nBufs, globalGain, globalGainPos) |
|
653 |
|
654 Input : bs - input bitstream |
|
655 aac - AAC decoder handle |
|
656 nBufs - # of gain buffers present |
|
657 |
|
658 Output : y - # of gain elements extracted |
|
659 globalGain - 'global_gain' elements |
|
660 globalGainPos - position location (in bits) of each gain value. |
|
661 This information is used when storing the gain |
|
662 elements back to bitstream. |
|
663 |
|
664 Author(s) : Juha Ojanpera |
|
665 *************************************************************************/ |
|
666 |
|
667 EXPORT_C uint8 |
|
668 GetAACGlobalGains(TBitStream* bs, CAACAudDec *aac, uint8 nBufs, uint8 *globalGain, uint32 *globalGainPos) |
|
669 { |
|
670 uint8 numGains; |
|
671 uint8 loopControl; |
|
672 TProgConfig progCfg; |
|
673 CMC_Info *mip = aac->mc_info; |
|
674 uint32 ele_id, prevEleID, bufBitOffset; |
|
675 |
|
676 numGains = 0; |
|
677 loopControl = 0; |
|
678 prevEleID = ID_END; |
|
679 bufBitOffset = BsGetBitsRead(bs); |
|
680 |
|
681 /*-- Reset some modules. --*/ |
|
682 ResetMCInfo(mip); |
|
683 |
|
684 /*-- No SBR elements present by default. --*/ |
|
685 if(aac->sbrStream) |
|
686 aac->sbrStream->NrElements = 0; |
|
687 |
|
688 /*-- Loop until termination code found. --*/ |
|
689 while((ele_id = BsGetBits(bs, LEN_SE_ID)) != ID_END) |
|
690 { |
|
691 int16 parserErr; |
|
692 |
|
693 if(loopControl > 64) break; |
|
694 |
|
695 /*-- Get audio syntactic element. --*/ |
|
696 switch(ele_id) |
|
697 { |
|
698 /*-- Single and lfe channel. --*/ |
|
699 case ID_SCE: |
|
700 case ID_LFE: |
|
701 if((numGains + 1) > nBufs) break; |
|
702 |
|
703 if(aac->sbrStream) |
|
704 SaveSBRChannelElementPos(aac->sbrStream, BsGetBitsRead(bs) - bufBitOffset, ele_id); |
|
705 |
|
706 if(globalGain) |
|
707 parserErr = GetSCEGain(aac, bs, &globalGain[numGains], &globalGainPos[numGains], bufBitOffset); |
|
708 else |
|
709 parserErr = GetSCE(aac, bs, mip, NULL, NULL, 0); |
|
710 |
|
711 if(parserErr < 0) |
|
712 goto f_out; |
|
713 numGains += 1; |
|
714 |
|
715 if(aac->sbrStream) |
|
716 SaveSBRChannelElementLen(aac->sbrStream, BsGetBitsRead(bs)); |
|
717 break; |
|
718 |
|
719 /*-- Channel pair element. --*/ |
|
720 case ID_CPE: |
|
721 if((numGains + 2) > nBufs) break; |
|
722 if(aac->sbrStream) |
|
723 SaveSBRChannelElementPos(aac->sbrStream, BsGetBitsRead(bs) - bufBitOffset, ele_id); |
|
724 |
|
725 if(globalGain) |
|
726 parserErr = GetCPEGain(aac, bs, &globalGain[numGains], &globalGainPos[numGains], bufBitOffset); |
|
727 else |
|
728 parserErr = GetCPE(aac, bs, mip, NULL, NULL, 0); |
|
729 |
|
730 if(parserErr < 0) |
|
731 goto f_out; |
|
732 numGains += 2; |
|
733 |
|
734 if(aac->sbrStream) |
|
735 SaveSBRChannelElementLen(aac->sbrStream, BsGetBitsRead(bs)); |
|
736 break; |
|
737 |
|
738 /*-- Coupling channel. --*/ |
|
739 case ID_CCE: |
|
740 if(GetCCE(aac, bs, mip, aac->ccInfo) < 0) |
|
741 goto f_out; |
|
742 break; |
|
743 |
|
744 /*-- Data element. --*/ |
|
745 case ID_DSE: |
|
746 loopControl++; |
|
747 GetDSE(bs); |
|
748 break; |
|
749 |
|
750 /*-- Program config element. --*/ |
|
751 case ID_PCE: |
|
752 loopControl++; |
|
753 GetPCE(bs, &progCfg); |
|
754 break; |
|
755 |
|
756 /*-- Fill element. --*/ |
|
757 case ID_FIL: |
|
758 loopControl++; |
|
759 TInt error; |
|
760 TRAP( error, aac->GetFIL(bs, prevEleID) ); |
|
761 if (error != KErrNone) |
|
762 goto f_out; |
|
763 break; |
|
764 |
|
765 default: |
|
766 goto f_out; |
|
767 } |
|
768 |
|
769 prevEleID = ele_id; |
|
770 |
|
771 bufBitOffset = BsGetBitsRead(bs) - bufBitOffset; |
|
772 } |
|
773 |
|
774 BsByteAlign(bs); |
|
775 |
|
776 f_out: |
|
777 |
|
778 return (numGains); |
|
779 } |
|
780 |
|
781 /* |
|
782 * Stores 'global_gain' bitstream elements to AAC data buffer. |
|
783 */ |
|
784 INLINE void |
|
785 SetAACGain(TBitStream* bs, uint32 gainPos, uint8 globalGains) |
|
786 { |
|
787 BsSkipNBits(bs, gainPos); |
|
788 BsPutBits(bs, LEN_SCL_PCM, globalGains); |
|
789 } |
|
790 |
|
791 /* |
|
792 * Saves modified 'global_gain' bitstream elements to specified AAC data buffer. |
|
793 */ |
|
794 EXPORT_C void |
|
795 SetAACGlobalGains(TBitStream* bs, uint8 numGains, uint8 *globalGain, uint32 *globalGainPos) |
|
796 { |
|
797 int16 i; |
|
798 TBitStream bsIn; |
|
799 |
|
800 BsSaveBufState(bs, &bsIn); |
|
801 |
|
802 /*-- Store the gain element back to bitstream. --*/ |
|
803 for(i = 0; i < numGains; i++) |
|
804 SetAACGain(bs, globalGainPos[i], globalGain[i]); |
|
805 |
|
806 |
|
807 } |
|
808 |
|
809 /* |
|
810 * Retrieves sample rate index corresponding to the specified sample rate. |
|
811 */ |
|
812 INLINE uint8 |
|
813 GetSampleRateIndex(int32 sampleRate) |
|
814 { |
|
815 uint8 sIndex = 0xF; |
|
816 |
|
817 switch(sampleRate) |
|
818 { |
|
819 case 96000: |
|
820 sIndex = 0x0; |
|
821 break; |
|
822 |
|
823 case 88200: |
|
824 sIndex = 0x1; |
|
825 break; |
|
826 |
|
827 case 64000: |
|
828 sIndex = 0x2; |
|
829 break; |
|
830 |
|
831 case 48000: |
|
832 sIndex = 0x3; |
|
833 break; |
|
834 |
|
835 case 44100: |
|
836 sIndex = 0x4; |
|
837 break; |
|
838 |
|
839 case 32000: |
|
840 sIndex = 0x5; |
|
841 break; |
|
842 |
|
843 case 24000: |
|
844 sIndex = 0x6; |
|
845 break; |
|
846 |
|
847 case 22050: |
|
848 sIndex = 0x7; |
|
849 break; |
|
850 |
|
851 case 16000: |
|
852 sIndex = 0x8; |
|
853 break; |
|
854 |
|
855 case 12000: |
|
856 sIndex = 0x9; |
|
857 break; |
|
858 |
|
859 case 11025: |
|
860 sIndex = 0xa; |
|
861 break; |
|
862 |
|
863 case 8000: |
|
864 sIndex = 0xb; |
|
865 break; |
|
866 } |
|
867 |
|
868 return (sIndex); |
|
869 } |
|
870 |
|
871 INLINE int16 |
|
872 WriteGASpecificConfig(TBitStream *bsOut, int16 bitsWritten, int16 frameLen) |
|
873 { |
|
874 /*-- Frame length flag (1024-point or 960-point MDCT). --*/ |
|
875 bitsWritten += 1; |
|
876 BsPutBits(bsOut, 1, (frameLen == LN2) ? 0 : 1); |
|
877 |
|
878 /*-- No core coder. --*/ |
|
879 bitsWritten += 1; |
|
880 BsPutBits(bsOut, 1, 0); |
|
881 |
|
882 /*-- No extension flag. --*/ |
|
883 bitsWritten += 1; |
|
884 BsPutBits(bsOut, 1, 0); |
|
885 |
|
886 return (bitsWritten); |
|
887 } |
|
888 |
|
889 |
|
890 |
|
891 EXPORT_C int16 |
|
892 AACGetMP4ConfigInfo(int32 sampleRate, uint8 profile, uint8 nChannels, |
|
893 int16 frameLen, uint8 *pBuf, uint8 nBytesInBuf) |
|
894 { |
|
895 TBitStream bsOut; |
|
896 int16 nConfigBytes, bitsWritten; |
|
897 |
|
898 BsInit(&bsOut, pBuf, nBytesInBuf); |
|
899 |
|
900 /*-- Object type. --*/ |
|
901 bitsWritten = 5; |
|
902 BsPutBits(&bsOut, 5, profile + 1); |
|
903 |
|
904 /*-- Sample rate index. --*/ |
|
905 bitsWritten += 4; |
|
906 BsPutBits(&bsOut, 4, GetSampleRateIndex(sampleRate)); |
|
907 if(GetSampleRateIndex(sampleRate) == 0xF) |
|
908 { |
|
909 bitsWritten += 24; |
|
910 BsPutBits(&bsOut, 24, sampleRate); |
|
911 } |
|
912 |
|
913 /*-- # of channels. --*/ |
|
914 bitsWritten += 4; |
|
915 BsPutBits(&bsOut, 4, nChannels); |
|
916 |
|
917 /*-- Write GA specific info. --*/ |
|
918 bitsWritten = WriteGASpecificConfig(&bsOut, bitsWritten, frameLen); |
|
919 |
|
920 nConfigBytes = int16 ((bitsWritten & 7) ? (bitsWritten >> 3) + 1 : (bitsWritten >> 3)); |
|
921 |
|
922 return (nConfigBytes); |
|
923 } |
|
924 |
|
925 /* |
|
926 * Saves modified 'global_gain' bitstream elements to specified AAC data buffer. |
|
927 */ |
|
928 EXPORT_C void |
|
929 SetAACPlusGlobalGains(TBitStream* bs, TBitStream* bsOut, CAACAudDec *aac, int16 gainChangeValue, |
|
930 uint8 numGains, uint8 *globalGain, uint32 *globalGainPos) |
|
931 { |
|
932 int16 i; |
|
933 TBitStream bsIn; |
|
934 |
|
935 BsSaveBufState(bs, &bsIn); |
|
936 |
|
937 /*-- Store the gain element back to bitstream. --*/ |
|
938 for(i = 0; i < numGains; i++) |
|
939 { |
|
940 SetAACGain(bs, globalGainPos[i], globalGain[i]); |
|
941 } |
|
942 |
|
943 |
|
944 if(aac->sbrStream && aac->sbrDecInfo) |
|
945 { |
|
946 |
|
947 if(aac->sbrStream->NrElements) |
|
948 { |
|
949 ParseSBR(&bsIn, bsOut, aac->sbrDecInfo, aac->sbrStream, gainChangeValue); |
|
950 } |
|
951 |
|
952 |
|
953 } |
|
954 |
|
955 } |
|
956 |
|
957 |
|
958 EXPORT_C uint8 |
|
959 IsAACParametricStereoEnabled(CAACAudDec *aac) |
|
960 { |
|
961 |
|
962 return (IsSBRParametricStereoEnabled(aac->sbrDecInfo, aac->sbrStream)); |
|
963 |
|
964 } |
|
965 |
|
966 EXPORT_C uint8 |
|
967 IsAACSBREnabled(CAACAudDec *aac) |
|
968 { |
|
969 |
|
970 return (IsSBREnabled(aac->sbrStream)); |
|
971 |
|
972 |
|
973 } |
|