|
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 |
|
22 #include "ProcAACFrameHandler.h" |
|
23 #include "ProcFrameHandler.h" |
|
24 #include "ProcTools.h" |
|
25 #include "nok_bits.h" |
|
26 #include "AACAPI.h" |
|
27 |
|
28 #include <f32file.h> |
|
29 #include <e32math.h> |
|
30 |
|
31 |
|
32 TBool CProcAACFrameHandler::ManipulateGainL(const HBufC8* aFrameIn, HBufC8*& aFrameOut, TInt8 aGain) |
|
33 { |
|
34 |
|
35 if (aFrameIn == 0) |
|
36 return EFalse; |
|
37 |
|
38 |
|
39 TInt numBlocks = 1; |
|
40 TInt headerBytes = CalculateNumberOfHeaderBytes(aFrameIn, numBlocks); |
|
41 |
|
42 // Unfortunately const casting is needed to avoid unecessary temporary arrays |
|
43 // and we don't have a separate bitstream class for const objects |
|
44 // Just have to make very sure not to modify const descriptors!! |
|
45 TUint8* buf = const_cast<TUint8*>(aFrameIn->Right(aFrameIn->Size()-headerBytes).Ptr()); |
|
46 |
|
47 uint8* gains = new (ELeave) uint8[16]; |
|
48 uint32* gainPos = new (ELeave) uint32[16]; |
|
49 |
|
50 TInt bufLen = aFrameIn->Size()-headerBytes; |
|
51 |
|
52 TBitStream bs; |
|
53 TBitStream bs2; |
|
54 |
|
55 BsInit(&bs, buf, bufLen); |
|
56 BsInit(&bs2, buf, bufLen); |
|
57 |
|
58 for (TInt b = 0 ; b < numBlocks ; b++) |
|
59 { |
|
60 |
|
61 TInt b_i = bs.buf_index; |
|
62 iFrameStarts.Append(b_i+headerBytes); |
|
63 |
|
64 BsSaveBufState(&bs, &bs2); |
|
65 |
|
66 uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos); |
|
67 |
|
68 if (numberOfGains > 2) |
|
69 { |
|
70 // illegal frame?? |
|
71 delete[] gainPos; |
|
72 delete[] gains; |
|
73 return KErrGeneral; |
|
74 |
|
75 } |
|
76 |
|
77 if (bs.buf_index > 0) |
|
78 iFrameLengths.Append(bs.buf_index - b_i); |
|
79 else |
|
80 iFrameLengths.Append(bs.buf_len - b_i); |
|
81 |
|
82 if (headerBytes > 7) |
|
83 { |
|
84 bs.buf_index += 2; // crc |
|
85 bs.slots_read += 2; |
|
86 bs.bits_read += 16; |
|
87 |
|
88 } |
|
89 |
|
90 TInt tmpGain = aGain*500; |
|
91 int16 newGain = static_cast<int16>(tmpGain/1500); |
|
92 |
|
93 |
|
94 for (TInt a = 0 ; a < numberOfGains ; a++) |
|
95 { |
|
96 if (gains[a] + newGain > 255) |
|
97 { |
|
98 gains[a] = 255; |
|
99 } |
|
100 else if (gains[a] + newGain < 0) |
|
101 { |
|
102 gains[a] = 0; |
|
103 } |
|
104 else |
|
105 { |
|
106 gains[a] = static_cast<TUint8>(gains[a]+newGain); |
|
107 } |
|
108 } |
|
109 |
|
110 |
|
111 if (iAACInfo.isSBR || iAACInfo.iIsParametricStereo) |
|
112 { |
|
113 |
|
114 uint8 *data = new (ELeave) uint8[1024]; |
|
115 CleanupStack::PushL(data); |
|
116 TBitStream bsOut; |
|
117 |
|
118 BsInit(&bsOut, data, 1024); |
|
119 |
|
120 SetAACPlusGlobalGains(&bs2, &bsOut, iDecHandle, static_cast<int16>(-newGain), numberOfGains, gains, gainPos); |
|
121 |
|
122 TInt incBytes = (bsOut.bits_read >> 3) - bs2.buf_len; |
|
123 iFrameLengths[iFrameLengths.Count()-1] +=incBytes; |
|
124 |
|
125 TInt newSize = aFrameIn->Size()+incBytes; |
|
126 aFrameOut = HBufC8::NewL(newSize); |
|
127 aFrameOut->Des().Append(aFrameIn->Left(headerBytes)); |
|
128 aFrameOut->Des().Append(bsOut.bit_buffer, bsOut.bits_read >> 3); |
|
129 |
|
130 if (headerBytes != 0) UpdateHeaderL(aFrameOut); |
|
131 |
|
132 CleanupStack::Pop(data); |
|
133 delete[] data; |
|
134 data = 0; |
|
135 |
|
136 |
|
137 } |
|
138 else |
|
139 { |
|
140 SetAACGlobalGains(&bs2, numberOfGains, gains, gainPos); |
|
141 aFrameOut = HBufC8::NewL(aFrameIn->Size()); |
|
142 aFrameOut->Des().Copy(aFrameIn->Ptr(), aFrameIn->Size()); |
|
143 |
|
144 } |
|
145 |
|
146 |
|
147 |
|
148 // } |
|
149 |
|
150 } |
|
151 delete[] gains; |
|
152 delete[] gainPos; |
|
153 |
|
154 |
|
155 return ETrue; |
|
156 } |
|
157 |
|
158 TBool CProcAACFrameHandler::GetGainL(const HBufC8* aFrame, RArray<TInt>& aGains, TInt& aMaxGain) const |
|
159 { |
|
160 |
|
161 |
|
162 TInt numBlocks = 1; |
|
163 TInt headerBytes = CalculateNumberOfHeaderBytes(aFrame, numBlocks); |
|
164 |
|
165 //TBitStream bs; |
|
166 TUint8* buf = const_cast<TUint8*>(aFrame->Right(aFrame->Size()-headerBytes).Ptr()); |
|
167 //BsInit(&bs, buf, aFrame->Size()-headerBytes); |
|
168 |
|
169 uint8* gains = new (ELeave) uint8[16]; |
|
170 CleanupStack::PushL(gains); |
|
171 uint32* gainPos = new (ELeave) uint32[16]; |
|
172 CleanupStack::PushL(gainPos); |
|
173 |
|
174 //TPtr8 frameWithoutHeader = aFrame->Right(aFrame->Size()-headerBytes)); |
|
175 TInt bufLen = aFrame->Size()-headerBytes; |
|
176 |
|
177 TBitStream bs; |
|
178 |
|
179 |
|
180 BsInit(&bs, buf, bufLen); |
|
181 |
|
182 |
|
183 for (TInt b = 0 ; b < numBlocks ; b++) |
|
184 { |
|
185 |
|
186 uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos); |
|
187 |
|
188 for (TInt a = 0 ; a < numberOfGains ; a++) |
|
189 { |
|
190 aGains.Append(gains[a]); |
|
191 } |
|
192 |
|
193 if (headerBytes > 7) |
|
194 { |
|
195 bs.buf_index += 2; // crc |
|
196 bs.slots_read += 2; |
|
197 bs.bits_read += 16; |
|
198 |
|
199 } |
|
200 |
|
201 } |
|
202 CleanupStack::Pop(); //(gainPos) |
|
203 CleanupStack::Pop(); //(gains) |
|
204 delete[] gains; |
|
205 delete[] gainPos; |
|
206 |
|
207 aMaxGain = 255; |
|
208 return EFalse; |
|
209 |
|
210 |
|
211 |
|
212 } |
|
213 |
|
214 |
|
215 TBool CProcAACFrameHandler::GetNormalizingMargin(const HBufC8* aFrame, TInt8& aMargin) const |
|
216 |
|
217 { |
|
218 |
|
219 TUint8* buf = const_cast<TUint8*>(aFrame->Ptr()); |
|
220 TInt bufLen = aFrame->Size(); |
|
221 |
|
222 uint8* gains = new uint8[16]; |
|
223 |
|
224 uint32* gainPos = new uint32[16]; |
|
225 |
|
226 |
|
227 TBitStream bs; |
|
228 |
|
229 BsInit(&bs, buf, bufLen); |
|
230 |
|
231 uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos); |
|
232 |
|
233 TUint8 maxGain = 0; |
|
234 |
|
235 for (TInt a = 0 ; a < numberOfGains ; a++) |
|
236 { |
|
237 if (gains[a] > maxGain) |
|
238 { |
|
239 maxGain = gains[a]; |
|
240 } |
|
241 } |
|
242 delete[] gains; |
|
243 delete[] gainPos; |
|
244 |
|
245 TInt marginInt = (255-maxGain)*6; |
|
246 |
|
247 if (marginInt > 127) |
|
248 { |
|
249 aMargin = 127; |
|
250 } |
|
251 else if (marginInt < 0) |
|
252 { |
|
253 aMargin = 0; |
|
254 } |
|
255 else |
|
256 { |
|
257 aMargin = static_cast<TInt8>(marginInt); |
|
258 } |
|
259 |
|
260 return ETrue; |
|
261 |
|
262 |
|
263 } |
|
264 |
|
265 CProcAACFrameHandler::~CProcAACFrameHandler() |
|
266 { |
|
267 |
|
268 iFrameStarts.Reset(); |
|
269 iFrameLengths.Reset(); |
|
270 if (iDecHandle != 0) |
|
271 { |
|
272 |
|
273 DeleteAACAudDec(iDecHandle); |
|
274 } |
|
275 |
|
276 |
|
277 } |
|
278 |
|
279 CProcAACFrameHandler* CProcAACFrameHandler::NewL(TAACFrameHandlerInfo aAACInfo) |
|
280 { |
|
281 |
|
282 |
|
283 CProcAACFrameHandler* self = NewLC(aAACInfo); |
|
284 CleanupStack::Pop(self); |
|
285 return self; |
|
286 |
|
287 } |
|
288 CProcAACFrameHandler* CProcAACFrameHandler::NewLC(TAACFrameHandlerInfo aAACInfo) |
|
289 { |
|
290 |
|
291 CProcAACFrameHandler* self = new (ELeave) CProcAACFrameHandler(); |
|
292 CleanupStack::PushL(self); |
|
293 self->ConstructL(aAACInfo); |
|
294 return self; |
|
295 |
|
296 } |
|
297 |
|
298 void CProcAACFrameHandler::ConstructL(TAACFrameHandlerInfo aAACInfo) |
|
299 { |
|
300 |
|
301 CreateAACAudDecL(iDecHandle, static_cast<TInt16>(aAACInfo.iNumChannels), |
|
302 static_cast<TInt16>(aAACInfo.iNumCouplingChannels)); |
|
303 |
|
304 InitAACAudDec(iDecHandle, static_cast<TInt16>(aAACInfo.iProfileID), |
|
305 static_cast<TInt16>(aAACInfo.iSampleRateID), |
|
306 static_cast<TUint8>(aAACInfo.iIs960)); |
|
307 |
|
308 if(aAACInfo.isSBR) |
|
309 { |
|
310 uint8 isStereo; |
|
311 |
|
312 isStereo = (aAACInfo.iNumChannels > 1) ? 1 : 0; |
|
313 |
|
314 CreateAACPlusAudDecL(iDecHandle, static_cast<TInt16>(aAACInfo.iSampleRateID), isStereo, (uint8) 0); |
|
315 } |
|
316 iAACInfo = aAACInfo; |
|
317 |
|
318 } |
|
319 |
|
320 CProcAACFrameHandler::CProcAACFrameHandler() : iDecHandle(0) |
|
321 { |
|
322 |
|
323 } |
|
324 |
|
325 TInt CProcAACFrameHandler::CalculateNumberOfHeaderBytes(const HBufC8* aFrame, TInt& aNumBlocksInFrame) const |
|
326 { |
|
327 |
|
328 if (aFrame->Size() < 7) return 0; |
|
329 TBuf8<7> possibleHeader(aFrame->Left(7)); |
|
330 |
|
331 TUint8 byte2 = possibleHeader[1]; |
|
332 TBuf8<8> byte2b; |
|
333 ProcTools::Dec2Bin(byte2, byte2b); |
|
334 TUint8 byte7 = possibleHeader[6]; |
|
335 |
|
336 // lets confirm that we have found a legal AAC header |
|
337 if (possibleHeader[0] == 0xFF && |
|
338 byte2b[0] == '1' && |
|
339 byte2b[1] == '1' && |
|
340 byte2b[2] == '1' && |
|
341 byte2b[3] == '1' && |
|
342 // byte2b[4] == '1' && |
|
343 byte2b[5] == '0' && |
|
344 byte2b[6] == '0') |
|
345 { |
|
346 |
|
347 aNumBlocksInFrame = (byte7 & 0x3)+1; |
|
348 |
|
349 |
|
350 // protection_absent -> the last bit of the second byte |
|
351 if (byte2b[7] == '0') |
|
352 { |
|
353 return 9 + 2*(aNumBlocksInFrame-1); |
|
354 } |
|
355 else |
|
356 { |
|
357 return 7; |
|
358 } |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 } |
|
365 else |
|
366 { |
|
367 // it seems like a raw data block |
|
368 return 0; |
|
369 |
|
370 |
|
371 |
|
372 } |
|
373 } |
|
374 |
|
375 |
|
376 |
|
377 TBool CProcAACFrameHandler::ParseFramesL(HBufC8* aFrame, RArray<TInt>& aFrameStarts, RArray<TInt>& aFrameLengths) |
|
378 { |
|
379 if (iFrameStarts.Count() > 0) |
|
380 { |
|
381 for (TInt a = 0 ; a < iFrameStarts.Count() ; a++) |
|
382 { |
|
383 aFrameStarts.Append(iFrameStarts[a]); |
|
384 aFrameLengths.Append(iFrameLengths[a]); |
|
385 } |
|
386 iFrameStarts.Reset(); |
|
387 iFrameLengths.Reset(); |
|
388 return ETrue; |
|
389 } |
|
390 else |
|
391 { |
|
392 |
|
393 TInt numBlocks = 1; |
|
394 TInt headerBytes = CalculateNumberOfHeaderBytes(aFrame, numBlocks); |
|
395 if (headerBytes > 0) |
|
396 { |
|
397 //TBuf8<headerBytes> hB(aFrame->Left(headerBytes)); |
|
398 |
|
399 |
|
400 } |
|
401 |
|
402 //TBitStream bs; |
|
403 TUint8* buf = const_cast<TUint8*>(aFrame->Right(aFrame->Size()-headerBytes).Ptr()); |
|
404 //BsInit(&bs, buf, aFrame->Size()-headerBytes); |
|
405 |
|
406 uint8* gains = new (ELeave) uint8[16]; |
|
407 CleanupStack::PushL(gains); |
|
408 uint32* gainPos = new (ELeave) uint32[16]; |
|
409 CleanupStack::PushL(gainPos); |
|
410 |
|
411 //TPtr8 frameWithoutHeader = aFrame->Right(aFrame->Size()-headerBytes)); |
|
412 TInt bufLen = aFrame->Size()-headerBytes; |
|
413 |
|
414 TBitStream bs; |
|
415 |
|
416 BsInit(&bs, buf, bufLen); |
|
417 |
|
418 for (TInt b = 0 ; b < numBlocks ; b++) |
|
419 { |
|
420 |
|
421 TInt b_i = bs.buf_index; |
|
422 iFrameStarts.Append(b_i+headerBytes); |
|
423 |
|
424 uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos); |
|
425 if (numberOfGains > 2) |
|
426 { |
|
427 CleanupStack::Pop(); // gainPos |
|
428 CleanupStack::Pop(); // gains |
|
429 delete[] gains; |
|
430 delete[] gainPos; |
|
431 return EFalse; |
|
432 |
|
433 } |
|
434 |
|
435 if (bs.buf_index > 0) |
|
436 iFrameLengths.Append(bs.buf_index - b_i); |
|
437 else |
|
438 iFrameLengths.Append(bs.buf_len - b_i); |
|
439 |
|
440 if (headerBytes > 7) |
|
441 { |
|
442 bs.buf_index += 2; // crc |
|
443 bs.slots_read += 2; |
|
444 bs.bits_read += 16; |
|
445 |
|
446 } |
|
447 |
|
448 } |
|
449 CleanupStack::Pop(); // gainPos |
|
450 CleanupStack::Pop(); // gains |
|
451 delete[] gains; |
|
452 delete[] gainPos; |
|
453 |
|
454 |
|
455 |
|
456 for (TInt c = 0 ; c < iFrameStarts.Count() ; c++) |
|
457 { |
|
458 aFrameStarts.Append(iFrameStarts[c]); |
|
459 aFrameLengths.Append(iFrameLengths[c]); |
|
460 } |
|
461 iFrameStarts.Reset(); |
|
462 iFrameLengths.Reset(); |
|
463 return ETrue; |
|
464 |
|
465 } |
|
466 |
|
467 |
|
468 |
|
469 |
|
470 } |
|
471 |
|
472 |
|
473 |
|
474 TBool CProcAACFrameHandler::UpdateHeaderL(HBufC8* aFrame) |
|
475 { |
|
476 |
|
477 _LIT8(KZero, "0"); |
|
478 |
|
479 TInt frameLength = aFrame->Size(); |
|
480 |
|
481 HBufC8* lenBin; |
|
482 ProcTools::Dec2BinL(frameLength, lenBin); |
|
483 |
|
484 HBufC8* len13Bin = HBufC8::NewL(13); |
|
485 TInt zerosNeeded = 13-lenBin->Size(); |
|
486 |
|
487 TPtr8 framePtr(aFrame->Des()); |
|
488 for (TInt w = 0 ; w < zerosNeeded ; w++) |
|
489 { |
|
490 len13Bin->Des().Append(_L8("0")); |
|
491 } |
|
492 len13Bin->Des().Append(lenBin->Des()); |
|
493 |
|
494 if (len13Bin->Mid(0,1).Compare(KZero) == 0) |
|
495 { |
|
496 framePtr[3] &= 0xFD; // 1111 1101 |
|
497 } |
|
498 else |
|
499 { |
|
500 framePtr[3] |= 2; |
|
501 } |
|
502 |
|
503 if (len13Bin->Mid(1,1).Compare(KZero) == 0) |
|
504 { |
|
505 framePtr[3] &= 0xFE; // 1111 1110 |
|
506 |
|
507 } |
|
508 else |
|
509 { |
|
510 framePtr[3] |= 1; |
|
511 } |
|
512 |
|
513 |
|
514 TUint byte5 = 0; |
|
515 ProcTools::Bin2Dec(len13Bin->Mid(2,8),byte5); |
|
516 framePtr[4] = static_cast<TUint8>(byte5); |
|
517 |
|
518 if (len13Bin->Mid(10,1).Compare(KZero) == 0) |
|
519 { |
|
520 framePtr[5] &= 0x7F; |
|
521 |
|
522 } |
|
523 else |
|
524 { |
|
525 framePtr[5] |= 0x80; |
|
526 } |
|
527 |
|
528 if (len13Bin->Mid(11,1).Compare(KZero) == 0) |
|
529 { |
|
530 framePtr[5] &= 0xBF; |
|
531 |
|
532 } |
|
533 else |
|
534 { |
|
535 framePtr[5] |= 0x40; |
|
536 } |
|
537 |
|
538 if (len13Bin->Mid(12,1).Compare(KZero) == 0) |
|
539 { |
|
540 framePtr[5] &= 0xDF; |
|
541 |
|
542 } |
|
543 else |
|
544 { |
|
545 framePtr[5] |= 0x20; |
|
546 } |
|
547 delete lenBin; |
|
548 delete len13Bin; |
|
549 return ETrue; |
|
550 } |
|
551 |
|
552 |
|
553 |
|
554 void CProcAACFrameHandler:: |
|
555 GetEnhancedAACPlusParametersL(TUint8* buf, TInt bufLen, |
|
556 TAudFileProperties* aProperties, |
|
557 TAACFrameHandlerInfo *aAACInfo) |
|
558 { |
|
559 TBitStream bs; |
|
560 uint8 sbrStatus; |
|
561 int16 bytesInFrame; |
|
562 CAACAudDec* decHandle = 0; |
|
563 |
|
564 //-- No SBR by default. --// |
|
565 aAACInfo->isSBR = 0; |
|
566 aAACInfo->iIsParametricStereo = 0; |
|
567 aProperties->iAudioTypeExtension = EAudExtensionTypeNoExtension; |
|
568 aProperties->iChannelModeExtension = EAudChannelModeNotRecognized; |
|
569 |
|
570 //-- Create AAC handle. --// |
|
571 CreateAACAudDecL(decHandle, |
|
572 static_cast<TInt16>(aAACInfo->iNumChannels), |
|
573 static_cast<TInt16>(aAACInfo->iNumCouplingChannels)); |
|
574 CleanupStack::PushL(decHandle); |
|
575 |
|
576 //-- Initialize AAC handle. --/ |
|
577 InitAACAudDec(decHandle, |
|
578 static_cast<TInt16>(aAACInfo->iProfileID), |
|
579 static_cast<TInt16>(aAACInfo->iSampleRateID), |
|
580 static_cast<TUint8>(aAACInfo->iIs960)); |
|
581 |
|
582 //-- Create SBR handle on top of the AAC handle. -- |
|
583 sbrStatus = CreateAACPlusAudDecL(decHandle, static_cast<TInt16>(aAACInfo->iSampleRateID), |
|
584 (uint8) ((aAACInfo->iNumChannels > 1) ? 1 : 0), |
|
585 (uint8) 0); |
|
586 |
|
587 if(sbrStatus) |
|
588 { |
|
589 //-- Initialize bitstream. -- |
|
590 BsInit(&bs, buf, bufLen); |
|
591 |
|
592 //-- Parse the AAC frame. --/ |
|
593 CountAACChunkLength(&bs, decHandle, &bytesInFrame); |
|
594 |
|
595 //-- Were any SBR elements found? -- |
|
596 if(IsAACSBREnabled(decHandle)) |
|
597 { |
|
598 aAACInfo->isSBR = 1; |
|
599 aProperties->iAudioTypeExtension = EAudExtensionTypeEnhancedAACPlus; |
|
600 |
|
601 aAACInfo->iIsParametricStereo = IsAACParametricStereoEnabled(decHandle); |
|
602 |
|
603 if(aAACInfo->iIsParametricStereo) |
|
604 { |
|
605 aProperties->iChannelModeExtension = EAudParametricStereoChannel; |
|
606 aProperties->iAudioTypeExtension = EAudExtensionTypeEnhancedAACPlusParametricStereo; |
|
607 } |
|
608 } |
|
609 } |
|
610 |
|
611 |
|
612 //-- Delete resources. --/ |
|
613 CleanupStack::Pop(decHandle); |
|
614 if(decHandle != 0) |
|
615 { |
|
616 DeleteAACAudDec(decHandle); |
|
617 } |
|
618 |
|
619 decHandle = 0; |
|
620 } |