• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 
19 /*----------------------------------------------------------------------------
20 ; INCLUDES
21 ----------------------------------------------------------------------------*/
22 
23 #include "amr_dec.h"
24 #include "frame.h"
25 #include "cnst.h"
26 #include "d_homing.h"
27 
28 #define ETS_INPUT_FRAME_SIZE 500
29 
30 //Compressed audio formats
31 #define PV_AMR_IETF                 0
32 #define PV_AMR_IF2                  1
33 #define PV_AMR_ETS                  2
34 #define PV_AMR_IETF_COMBINED        3
35 
36 //WB modes
37 #define PV_AMRWB_IETF_PAYLOAD        4
38 #define PV_AMRWB_IETF                5
39 
40 
41 // decoder returns -1 if there is an error in decoding a frame
42 #define PV_GSMAMR_DECODE_STATUS_ERR -1
43 
44 // Currently, decoder returns a value >=0 if there is no error.(should be 0)
45 #define PV_GSMAMR_DECODE_STATUS_OK 0
46 
47 // Find frame size for each frame type
48 static const OMX_S32 WBIETFFrameSize[16] =
49 {
50     18      // AMR-WB 6.60 Kbps
51     , 24        // AMR-WB 8.85 Kbps
52     , 33        // AMR-WB 12.65 Kbps
53     , 37        // AMR-WB 14.25 Kbps
54     , 41        // AMR-WB 15.85 Kbps
55     , 47        // AMR-WB 18.25 Kbps
56     , 51        // AMR-WB 19.85 Kbps
57     , 59        // AMR-WB 23.05 Kbps
58     , 61        // AMR-WB 23.85 Kbps
59     , 6     // AMR-WB SID
60     , 1
61     , 1
62     , 1
63     , 1
64     , 1     // WBAMR Frame No Data
65     , 1     // WBAMR Frame No Data
66 };
67 
68 //////////////////////////////////////////////////////////////////////////////////
69 static const OMX_S32 IETFFrameSize[16] =
70 {
71     13      // AMR 4.75 Kbps
72     , 14        // AMR 5.15 Kbps
73     , 16        // AMR 5.90 Kbps
74     , 18        // AMR 6.70 Kbps
75     , 20        // AMR 7.40 Kbps
76     , 21        // AMR 7.95 Kbps
77     , 27        // AMR 10.2 Kbps
78     , 32        // AMR 12.2 Kbps
79     , 6     // GsmAmr comfort noise
80     , 7     // Gsm-Efr comfort noise
81     , 6     // IS-641 comfort noise
82     , 6     // Pdc-Efr comfort noise
83     , 1     // future use; 0 length but set to 1 to skip the frame type byte
84     , 1     // future use; 0 length but set to 1 to skip the frame type byte
85     , 1     // future use; 0 length but set to 1 to skip the frame type byte
86     , 1     // AMR Frame No Data
87 };
88 
89 static const OMX_S32 IF2FrameSize[16] =
90 {
91     13      // AMR 4.75 Kbps
92     , 14        // AMR 5.15 Kbps
93     , 16        // AMR 5.90 Kbps
94     , 18        // AMR 6.70 Kbps
95     , 19        // AMR 7.40 Kbps
96     , 21        // AMR 7.95 Kbps
97     , 26        // AMR 10.2 Kbps
98     , 31        // AMR 12.2 Kbps
99     , 6     // AMR Frame SID
100     , 6     // AMR Frame GSM EFR SID
101     , 6     // AMR Frame TDMA EFR SID
102     , 6     // AMR Frame PDC EFR SID
103     , 1     // future use; 0 length but set to 1 to skip the frame type byte
104     , 1     // future use; 0 length but set to 1 to skip the frame type byte
105     , 1     // future use; 0 length but set to 1 to skip the frame type byte
106     , 1     // AMR Frame No Data
107 };
108 
OmxAmrDecoder()109 OmxAmrDecoder::OmxAmrDecoder()
110 {
111     iOmxInputFormat = PV_AMR_ETS;
112     iAMRFramesinTOC = 0;
113     iAmrInitFlag = 0;
114     iNarrowBandFlag = OMX_TRUE;
115 
116     //Output frame size in NB would be double the L_FRAME, due to char* output buffer in case of openmax instead of short* in console app
117     iOutputFrameSize = L_FRAME * 2;
118 
119     iCodecExternals = NULL;
120     iAudioAmrDecoder = NULL;
121     iTocTablePtr = NULL;
122     /* Initialize decoder homing flags */
123     iDecHomingFlag = 0;
124     iDecHomingFlagOld = 1;
125 }
126 
127 /* Decoder Initialization function */
AmrDecInit(OMX_AUDIO_AMRFRAMEFORMATTYPE aInFormat,OMX_AUDIO_AMRBANDMODETYPE aInMode)128 OMX_BOOL OmxAmrDecoder::AmrDecInit(OMX_AUDIO_AMRFRAMEFORMATTYPE aInFormat, OMX_AUDIO_AMRBANDMODETYPE aInMode)
129 {
130     OMX_S32 Status = 0;
131 
132     iAmrInitFlag = 0;
133 
134     if ((aInMode >= OMX_AUDIO_AMRBandModeNB0) && (aInMode <= OMX_AUDIO_AMRBandModeNB7))
135     {
136         iAudioAmrDecoder = CDecoder_AMR_NB::NewL();
137 
138         if (!iAudioAmrDecoder)
139         {
140             return OMX_FALSE;
141         }
142 
143         iNarrowBandFlag = OMX_TRUE;
144         iOutputFrameSize = L_FRAME * 2;
145     }
146 
147     else if ((aInMode >= OMX_AUDIO_AMRBandModeWB0) && (aInMode <= OMX_AUDIO_AMRBandModeWB8))
148     {
149         iAudioAmrDecoder = CDecoder_AMR_WB::NewL();
150 
151         if (!iAudioAmrDecoder)
152         {
153             return OMX_FALSE;
154         }
155 
156         iNarrowBandFlag = OMX_FALSE;
157         iOutputFrameSize = L_FRAME * 4;
158     }
159     else
160     {
161         return OMX_FALSE;
162     }
163 
164 
165     if (!iCodecExternals)
166     {
167         iCodecExternals = OSCL_NEW(tPVAmrDecoderExternal, ());
168         if (!iCodecExternals)
169         {
170             return OMX_FALSE;
171         }
172     }
173 
174     //initialize all fields to 0
175     oscl_memset(iCodecExternals, 0, sizeof(tPVAmrDecoderExternal));
176     iCodecExternals->quality = 1;  // assume its always good data
177 
178     //Extracting the input format information
179     if (OMX_AUDIO_AMRFrameFormatConformance == aInFormat)
180     {
181         iOmxInputFormat = PV_AMR_ETS;
182         iCodecExternals->input_format = ETS;
183     }
184     else if (OMX_AUDIO_AMRFrameFormatIF2 == aInFormat)
185     {
186         iOmxInputFormat = PV_AMR_IF2;
187         iCodecExternals->input_format = IF2;
188     }
189     else if (OMX_AUDIO_AMRFrameFormatRTPPayload == aInFormat)
190     {
191         if (OMX_TRUE == iNarrowBandFlag)
192         {
193             iOmxInputFormat = PV_AMR_IETF_COMBINED;
194         }
195         else
196         {
197             iOmxInputFormat = PV_AMRWB_IETF_PAYLOAD;
198         }
199 
200         iCodecExternals->input_format = MIME_IETF;
201     }
202     else if (OMX_AUDIO_AMRFrameFormatFSF == aInFormat)
203     {
204         if (OMX_TRUE == iNarrowBandFlag)
205         {
206             iOmxInputFormat = PV_AMR_IETF;
207         }
208         else
209         {
210             iOmxInputFormat = PV_AMRWB_IETF;
211         }
212 
213         iCodecExternals->input_format = MIME_IETF;
214     }
215 
216     Status = iAudioAmrDecoder->StartL(iCodecExternals, false, false);
217 
218     if (Status)
219     {
220         return OMX_FALSE;
221     }
222 
223     return OMX_TRUE;
224 }
225 
226 
227 /* Decoder De-Initialization function */
AmrDecDeinit()228 void OmxAmrDecoder::AmrDecDeinit()
229 {
230     /* This function call is platform-specific */
231     if (iAudioAmrDecoder)
232     {
233         iAudioAmrDecoder->TerminateDecoderL();
234         OSCL_DELETE(iAudioAmrDecoder);
235         iAudioAmrDecoder = NULL;
236 
237         if (iCodecExternals)
238         {
239             OSCL_DELETE(iCodecExternals);
240             iCodecExternals = NULL;
241         }
242     }
243 }
244 
245 
ResetDecoder()246 void OmxAmrDecoder::ResetDecoder()
247 {
248     if (iAudioAmrDecoder)
249     {
250         iAudioAmrDecoder->ResetDecoderL();
251     }
252     iAMRFramesinTOC = 0;
253 }
254 
255 
256 /* Find the start point & size of TOC table in case of IETF_Combined format */
GetStartPointsForIETFCombinedMode(OMX_U8 * aPtrIn,OMX_U32 aLength,OMX_U8 * & aTocPtr,OMX_S32 * aNumOfBytes)257 void OmxAmrDecoder::GetStartPointsForIETFCombinedMode
258 (OMX_U8* aPtrIn, OMX_U32 aLength, OMX_U8* &aTocPtr, OMX_S32* aNumOfBytes)
259 {
260     OMX_U8 Fbit     = 0x80;
261     OMX_U32 FrameCnt = 0;
262 
263     /* Count number of frames */
264     aTocPtr = aPtrIn;
265     while ((*(aTocPtr + FrameCnt) & Fbit) && (FrameCnt < aLength))
266     {
267         FrameCnt++;
268     }
269 
270     FrameCnt++;
271     *aNumOfBytes = FrameCnt;
272 }
273 
274 
275 /* Decode function for all the input formats */
AmrDecodeFrame(OMX_S16 * aOutputBuffer,OMX_U32 * aOutputLength,OMX_U8 ** aInBuffer,OMX_U32 * aInBufSize,OMX_S32 * aIsFirstBuffer)276 OMX_BOOL OmxAmrDecoder::AmrDecodeFrame(OMX_S16* aOutputBuffer,
277                                        OMX_U32* aOutputLength, OMX_U8** aInBuffer,
278                                        OMX_U32* aInBufSize, OMX_S32* aIsFirstBuffer)
279 {
280     OMX_BOOL Status = OMX_TRUE;
281     OMX_S32 ByteOffset, ii;
282     TXFrameType  TxFrame;
283 
284     /* 3GPP Frame Type Buffer */
285     Frame_Type_3GPP FrameType3gpp;
286 
287     /* Takes care of extra bytes above the decoded ones
288      * e.g. toc length for ietf_combined, frame header length &
289      * one frame type byte for ietf format.
290      */
291     OMX_S32 FrameBytesProcessed = 0, FrameLength;
292 
293     /* Reset speech_bits buffer pointer */
294     OMX_U8* pSpeechBits = *aInBuffer;
295     OMX_U8 *pTocPtr;
296     //ETS mode requires a 16-bit pointer
297     OMX_S16* pEtsSpeechBits = (OMX_S16*) * aInBuffer;
298 
299     if ((PV_AMR_IETF_COMBINED == iOmxInputFormat) || (PV_AMR_IETF == iOmxInputFormat)
300             || (PV_AMRWB_IETF_PAYLOAD == iOmxInputFormat) || (PV_AMRWB_IETF == iOmxInputFormat))
301     {
302         if ((PV_AMR_IETF_COMBINED == iOmxInputFormat) || (PV_AMRWB_IETF_PAYLOAD == iOmxInputFormat))
303         {
304             if (0 == iAMRFramesinTOC)
305             {
306                 pTocPtr = NULL;
307                 GetStartPointsForIETFCombinedMode(pSpeechBits, *aInBufSize,
308                                                   pTocPtr, &iAMRFramesinTOC);
309                 pSpeechBits += iAMRFramesinTOC;
310                 FrameBytesProcessed = iAMRFramesinTOC;
311 
312                 iTocTablePtr = pTocPtr;
313                 iAMRFramesinTOC--; // ctr of amr frames
314             }
315             else
316             {
317                 iAMRFramesinTOC--;
318                 FrameBytesProcessed = 0;
319             }
320 
321             FrameType3gpp = GetFrameTypeLength(iTocTablePtr, &FrameLength);
322         }
323         else //iOmxInputFormat == PV_AMR_IETF or (PV_AMRWB_IETF == iOmxInputFormat)
324         {
325             if (0 == iAmrInitFlag)
326             {
327                 if ('#' == pSpeechBits[0])
328                 {
329                     pSpeechBits += 6;
330                     FrameBytesProcessed = 6;
331                 }
332                 iAmrInitFlag = 1;
333             }
334 
335             FrameType3gpp = GetFrameTypeLength(pSpeechBits, &FrameLength);
336         }
337 
338         // check if the frame size exceeds buffer boundaries
339         if ((FrameLength + FrameBytesProcessed) <= (OMX_S32) *aInBufSize)
340         {
341             /* Set up pointer to the start of frame to be decoded */
342             iCodecExternals->mode = (uint32)FrameType3gpp;
343             iCodecExternals->pInputBuffer = (uint8*) pSpeechBits;
344             iCodecExternals->pOutputBuffer = (int16*) aOutputBuffer;
345 
346             ByteOffset = iAudioAmrDecoder->ExecuteL(iCodecExternals);
347 
348             if (PV_GSMAMR_DECODE_STATUS_ERR == ByteOffset)
349             {
350                 *aInBufSize = 0;
351                 *aOutputLength = 0;
352                 iAMRFramesinTOC = 0; // make sure the TOC table (if necessary) gets initialized for the next time
353                 Status = OMX_FALSE;
354             }
355             else
356             {
357                 *aInBufSize -= (FrameLength + FrameBytesProcessed);
358                 *aInBuffer += (FrameLength + FrameBytesProcessed);
359                 *aOutputLength = iOutputFrameSize;
360                 // in case of TOC, make sure that
361                 // a) if no more data in the buffer and TOC indicates more data, reset TOC
362                 // b) if TOC indicates no more data, and there is more data in the buffer, reset the buffer
363                 if ((PV_AMR_IETF_COMBINED == iOmxInputFormat) || (PV_AMRWB_IETF_PAYLOAD == iOmxInputFormat))
364                 {
365                     if ((0 == iAMRFramesinTOC) || (0 == *aInBufSize))
366                     {
367                         *aInBufSize = 0;
368                         iAMRFramesinTOC = 0;
369                     }
370                 }
371 
372             }
373         }
374         else
375         {
376             *aInBufSize = 0;
377             *aOutputLength = 0;
378             iAMRFramesinTOC = 0; // make sure the TOC table (if necessary) gets initialized for the next time
379             Status = OMX_FALSE; // treat buffer overrun as an error
380         }
381 
382     }
383     else if (PV_AMR_IF2 == iOmxInputFormat)
384     {
385         FrameType3gpp = (Frame_Type_3GPP)(pSpeechBits[0] & 0xF);
386         FrameLength = IF2FrameSize[FrameType3gpp];
387 
388         // check if the frame size exceeds buffer boundaries
389         if ((FrameLength + FrameBytesProcessed) <= (OMX_S32) *aInBufSize)
390         {
391             /* Set up pointer to the start of frame to be decoded */
392             iCodecExternals->mode = (uint32)FrameType3gpp;
393             iCodecExternals->pInputBuffer = (uint8*) pSpeechBits;
394             iCodecExternals->pOutputBuffer = (int16*) aOutputBuffer;
395 
396             ByteOffset = iAudioAmrDecoder->ExecuteL(iCodecExternals);
397 
398             if (PV_GSMAMR_DECODE_STATUS_ERR == ByteOffset)
399             {
400                 Status = OMX_FALSE;
401             }
402 
403             if (ByteOffset <= (OMX_S32)*aInBufSize)
404             {
405                 *aInBufSize -= ByteOffset;
406                 *aInBuffer += ByteOffset;
407                 *aOutputLength = iOutputFrameSize;
408             }
409             else
410             {
411                 *aInBufSize = 0;
412                 *aOutputLength = 0;
413                 Status = OMX_FALSE;
414             }
415         }
416         else
417         {
418             *aInBufSize = 0;
419             *aOutputLength = 0;
420             Status = OMX_FALSE; // treat buffer overrun as an error
421         }
422     }
423     else if (PV_AMR_ETS == iOmxInputFormat)
424     {
425         FrameType3gpp = (enum Frame_Type_3GPP) pSpeechBits[(1 + MAX_SERIAL_SIZE) * 2];
426 
427         /* Get TX frame type */
428         TxFrame = (TXFrameType)pEtsSpeechBits[0];
429 
430         /* Convert TX frame type to RX frame type */
431         switch (TxFrame)
432         {
433             case TX_SPEECH_GOOD:
434                 pEtsSpeechBits[0] = RX_SPEECH_GOOD;
435                 break;
436 
437             case TX_SPEECH_DEGRADED:
438                 pEtsSpeechBits[0] = RX_SPEECH_DEGRADED;
439                 break;
440 
441             case TX_SPEECH_BAD:
442                 pEtsSpeechBits[0] = RX_SPEECH_BAD;
443                 break;
444 
445             case TX_SID_FIRST:
446                 pEtsSpeechBits[0] = RX_SID_FIRST;
447                 break;
448 
449             case TX_SID_UPDATE:
450                 pEtsSpeechBits[0] = RX_SID_UPDATE;
451                 break;
452 
453             case TX_SID_BAD:
454                 pEtsSpeechBits[0] = RX_SID_BAD;
455                 break;
456 
457             case TX_ONSET:
458                 pEtsSpeechBits[0] = RX_ONSET;
459                 break;
460 
461             case TX_NO_DATA:
462                 pEtsSpeechBits[0] = RX_NO_DATA;
463                 FrameType3gpp = (enum Frame_Type_3GPP) iCodecExternals->mode;
464                 break;
465 
466             default:
467                 break;
468         }
469 
470         /* if homed: check if this frame is another homing frame */
471         if (1 == iDecHomingFlagOld)
472         {
473             /* only check until end of first subframe */
474             iDecHomingFlag = decoder_homing_frame_test_first(
475                                  (OMX_S16*) & pEtsSpeechBits[1],
476                                  (enum Mode) FrameType3gpp);
477         }
478 
479         /* produce encoder homing frame if homed & input=decoder homing frame */
480         if ((0 != iDecHomingFlag) && (0 != iDecHomingFlagOld))
481         {
482             for (ii = 0; ii < L_FRAME; ii++)
483             {
484                 aOutputBuffer[ii] = EHF_MASK;
485             }
486         }
487         else
488         {
489             /* Set up pointer to the start of frame to be decoded */
490             iCodecExternals->mode = (uint32)FrameType3gpp;
491             iCodecExternals->pInputBuffer = (uint8*) pEtsSpeechBits;
492             iCodecExternals->pOutputBuffer = (int16*) aOutputBuffer;
493 
494             ByteOffset = iAudioAmrDecoder->ExecuteL(iCodecExternals);
495 
496             if (PV_GSMAMR_DECODE_STATUS_ERR == ByteOffset)
497             {
498                 Status = OMX_FALSE;
499             }
500 
501         }
502 
503         /* if not homed: check whether current frame is a homing frame */
504         if (0 == iDecHomingFlagOld)
505         {
506             /* check whole frame */
507             iDecHomingFlag = decoder_homing_frame_test(
508                                  (OMX_S16*) & pEtsSpeechBits[1],
509                                  (enum Mode) FrameType3gpp);
510         }
511         /* reset decoder if current frame is a homing frame */
512         if (0 != iDecHomingFlag)
513         {
514             iAudioAmrDecoder->ResetDecoderL();
515         }
516 
517         iDecHomingFlagOld = iDecHomingFlag;
518 
519         //Input buffer requirement per frame is constant at ETS_INPUT_FRAME_SIZE
520         *aInBufSize -= ETS_INPUT_FRAME_SIZE;
521         *aInBuffer += ETS_INPUT_FRAME_SIZE;
522         *aOutputLength = iOutputFrameSize;
523     }
524 
525     (*aIsFirstBuffer)++;
526 
527     return Status;
528 }
529 
530 /* Decode function for all the input formats */
AmrDecodeSilenceFrame(OMX_S16 * aOutputBuffer,OMX_U32 * aOutputLength)531 OMX_BOOL OmxAmrDecoder::AmrDecodeSilenceFrame(OMX_S16* aOutputBuffer,
532         OMX_U32* aOutputLength)
533 {
534     OMX_BOOL Status = OMX_TRUE;
535     OMX_S32 ByteOffset;
536     OMX_U8 FrameType = 15; // silence frame
537 
538     iCodecExternals->mode = (uint32) FrameType;
539     iCodecExternals->pInputBuffer = (uint8*) & FrameType;
540     iCodecExternals->pOutputBuffer = (int16*) aOutputBuffer;
541 
542     ByteOffset = iAudioAmrDecoder->ExecuteL(iCodecExternals);
543 
544     if (PV_GSMAMR_DECODE_STATUS_ERR == ByteOffset)
545     {
546         Status = OMX_FALSE;
547     }
548     else
549     {
550         *aOutputLength = iOutputFrameSize;
551     }
552 
553     return Status;
554 }
555 
556 
557 /* Get Frame type for format == PVMF_AMR_IETF or PVMF_AMR_IETF_COMBINED and the WB counterparts*/
GetFrameTypeLength(OMX_U8 * & aFrame,OMX_S32 * aFrameLength)558 Frame_Type_3GPP OmxAmrDecoder::GetFrameTypeLength(OMX_U8* &aFrame, OMX_S32* aFrameLength)
559 {
560     Frame_Type_3GPP  FrameType3gpp;
561 
562 
563     FrameType3gpp = (Frame_Type_3GPP)((aFrame[0] >> 3) & 0x0F);
564 
565     //Narrow Band AMR
566     if (OMX_TRUE == iNarrowBandFlag)
567     {
568         *aFrameLength = IETFFrameSize[FrameType3gpp];
569     }
570     else
571     {
572         *aFrameLength = WBIETFFrameSize[FrameType3gpp];
573     }
574 
575 
576 
577     if (PV_AMR_IETF_COMBINED == iOmxInputFormat || PV_AMRWB_IETF_PAYLOAD == iOmxInputFormat)
578     {
579         // move ptr for TOC
580         aFrame++;
581         (*aFrameLength)--; // account for the 1 byte of length being not in the frame, but in the TOC
582     }
583     else if ((PV_AMR_IETF == iOmxInputFormat) || (PV_AMRWB_IETF == iOmxInputFormat))
584     {
585         aFrame++; // move ptr to data to skip the frame type/size field
586     }
587 
588 
589     return (FrameType3gpp);
590 }
591