Tizen 2.0 Release
[framework/osp/media.git] / src / FMedia_AacDecoder.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 #include <unique_ptr.h>
18 #include <FBaseColHashMap.h>
19 #include <FBaseColArrayListT.h>
20 #include <FMediaTypes.h>
21 #include <FMediaAudioTypes.h>
22 #include <FBaseSysLog.h>
23 #include <FBaseInteger.h>
24 #include "FMedia_Ffmpeg.h"
25 #include "FMedia_IAudioDecoder.h"
26 #include "FMedia_AacDecoder.h"
27 #include "FMedia_BitWriter.h"
28
29 using namespace Tizen::Base;
30 using namespace Tizen::Io;
31 using namespace Tizen::Base::Collection;
32
33 namespace Tizen { namespace Media
34 {
35
36 #define ADTS_HEADER_SIZE 7
37
38 static const int _AAC_SAMPLE_RATE_INDEX[] = {
39         96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 };
40
41 _IAudioDecoder*
42 _AacDecoder_CreateInstance(void)
43 {
44         return new (std::nothrow) _AacDecoder();
45 }
46
47 _AacDecoder::_AacDecoder(void)
48 {
49         __pCodecCtx = null;
50         __pCodec = null;
51         __decodeCalled = false;
52         __pOutBuf = null;
53 }
54
55 _AacDecoder::~_AacDecoder(void)
56 {
57         if (__pCodecCtx != null)
58         {
59                 avcodec_close(__pCodecCtx);
60                 av_free(__pCodecCtx);
61                 __pCodecCtx = null;
62                 __pCodec = null;
63         }
64         if (__pOutBuf != null)
65         {
66                 delete[] __pOutBuf;
67         }
68 }
69
70 result
71 _AacDecoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
72 {
73         result r = E_SUCCESS;
74         int res = 0;
75         Integer* pKey = null;
76         Integer* pValue = null;
77         int key = -1;
78         int value = -1;
79
80         SysAssertf((__pCodecCtx == null && __pCodec == null), " Already Constructed .");
81
82         avcodec_register_all();
83
84         __pCodecCtx = avcodec_alloc_context();
85         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
86                            "[%s] AVCODEC Context Allcoation Failed",GetErrorMessage(E_SYSTEM));
87         __pCodec = avcodec_find_decoder(CODEC_ID_AAC);
88         SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
89                            "[%s] AVCODEC Find Decoder Failed for CODEC_ID_AAC",GetErrorMessage(E_SYSTEM));
90
91         if (pOption != null)
92         {
93                 // The initialization values are given in the Hashmap
94                 std::unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
95                 if (pMapEnum.get() != null)
96                 {
97                         while (pMapEnum.get()->MoveNext() == E_SUCCESS)
98                         {
99                                 pKey = static_cast<Integer*>(pMapEnum.get()->GetKey());
100                                 pValue = static_cast<Integer*>(pMapEnum.get()->GetValue());
101                                 if (pKey && pValue)
102                                 {
103                                         key = pKey->ToInt();
104                                         value = pValue->ToInt();
105                                         switch (key)
106                                         {
107                                         case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
108                                                 SysTryCatch(NID_MEDIA, (value == 0 || value == 1 || value == 2), r = E_OUT_OF_RANGE,
109                                                                    E_OUT_OF_RANGE, "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
110                                                 __pCodecCtx->channels = value;
111                                                 break;
112
113                                         case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
114                                                 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
115                                                                    "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
116                                                 __pCodecCtx->sample_rate = value;
117                                                 break;
118
119                                         case MEDIA_PROPERTY_AUDIO_BIT_RATE:
120                                                 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
121                                                                    "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
122                                                 __pCodecCtx->bit_rate = value;
123                                                 break;
124
125                                         default:
126                                                 break;
127                                         }
128                                 }
129                         } // while
130                 }
131         }
132
133         __pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
134         res = avcodec_open(__pCodecCtx, __pCodec);
135         SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
136                            "[%s] AVCODEC Codec Open Failed for CODEC_ID_AAC",GetErrorMessage(E_SYSTEM));
137
138         // AVCodecContext parameters
139         if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
140         {
141                 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
142         }
143
144         __pCodecCtx->debug_mv = 0; //set by user
145         __pCodecCtx->debug = 0; //set by user
146         __pCodecCtx->workaround_bugs = 1; //set by user
147         __pCodecCtx->extradata_size = 0;
148
149         __pOutBuf = new (std::nothrow) byte[DEFAULT_BUFFER_SIZE];
150         SysTryCatch(NID_MEDIA, __pOutBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
151                            "[%s] Memory Allocation  Failed ",GetErrorMessage(E_OUT_OF_MEMORY)); 
152
153
154         return r;
155
156 CATCH:
157         if (__pCodecCtx != null)
158         {
159                 avcodec_close(__pCodecCtx);
160                 av_free(__pCodecCtx);
161                 __pCodecCtx = null;
162                 __pCodec = null;
163         }
164         return r;
165 }
166
167 const ByteBuffer*
168 _AacDecoder::GetHeaderN(int sampleRate, int channels, int size, int pce_size)
169 {
170         ByteBuffer* pBuf = null;
171         result r = E_SUCCESS;
172
173         pBuf = new (std::nothrow) ByteBuffer();
174
175         if (pBuf == null)
176         {
177                 return null;
178         }
179
180         r = pBuf->Construct(ADTS_HEADER_SIZE);
181         if (r != E_SUCCESS)
182         {
183                 delete pBuf;
184                 return null;
185         }
186
187         _BitWriter bw((byte*)pBuf->GetPointer(),pBuf->GetCapacity());
188         int sampleRateIndex = 0x0b;
189         int count = (int)(sizeof(_AAC_SAMPLE_RATE_INDEX)/sizeof(_AAC_SAMPLE_RATE_INDEX[0]));
190         for (int i = 0; i < count; i++)
191         {
192                 if (_AAC_SAMPLE_RATE_INDEX[i] == sampleRate)
193                 {
194                         sampleRateIndex = i;
195                         break;
196                 }
197         }
198
199         // fixed header
200         bw.PutBits(12, 0xfff);                  // syncword
201         bw.PutBits(1, 0);                               // id
202         bw.PutBits(2, 0);                               // layer
203         bw.PutBits(1, 1);                               // protection
204         bw.PutBits(2, 1);                               // profile : LC: 01
205         bw.PutBits(4, sampleRateIndex); // sample rate index
206         bw.PutBits(1, 0);                               // private
207         bw.PutBits(3, channels);                // channel
208         bw.PutBits(1, 0);                               // original copy
209         bw.PutBits(1, 0);                               // home
210
211         // variable header
212         bw.PutBits(1, 0);                               // copyright id bit
213         bw.PutBits(1, 0);                               // copyright id start
214         bw.PutBits(13, ADTS_HEADER_SIZE+size+pce_size);                         // aac frame length
215         bw.PutBits(11, 0x7ff);                  // buffer fullness
216         bw.PutBits(2, 0);                               // number of raw data blocks in frame
217
218         pBuf->SetPosition(0);
219         r = pBuf->SetLimit(ADTS_HEADER_SIZE);
220         if (r != E_SUCCESS)
221         {
222                 delete pBuf;
223                 return null;
224         }
225
226         return pBuf;
227 }
228
229 result
230 _AacDecoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
231                                         byte* pDstBuf, int dstBufSize, int& dstBufUsed)
232 {
233         result r = E_SUCCESS;
234         int res = 0;
235         AVPacket inputPacket;
236         int outBufSize = 0;
237         int16_t* pOutBuf = null;
238         int errStrLen = 256;
239         char errStr[errStrLen];
240         uint8_t* pInputData = null;
241         const  ByteBuffer* pAdtsHeader = null;
242
243
244         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
245                            "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
246         SysTryCatch(NID_MEDIA, (pSrcBuf != null && pDstBuf != null && srcBufSize > 0 && dstBufSize > 0),
247                            r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
248
249         av_init_packet(&inputPacket);
250         inputPacket.size = srcBufSize;
251         inputPacket.data = (uint8_t*)pSrcBuf;
252
253         if (dstBufSize >= DEFAULT_BUFFER_SIZE)
254         {
255                 pOutBuf = (int16_t*)pDstBuf;
256                 outBufSize = dstBufSize;
257         }
258         else
259         {
260                 pOutBuf = (int16_t*)__pOutBuf;
261                 outBufSize = DEFAULT_BUFFER_SIZE;
262         }
263
264         // Decoding the Audio  packet
265         res = avcodec_decode_audio3(__pCodecCtx, pOutBuf, &outBufSize, &inputPacket);
266         // add adts header and try to decode
267         if ( res < 0 && !((pSrcBuf[0] == 0xff) && ((pSrcBuf[1] & 0xf6) == 0xf0)))
268         {
269                 pInputData = new (std::nothrow) uint8_t[srcBufSize + ADTS_HEADER_SIZE];
270                 SysTryCatch(NID_MEDIA, pInputData != null, r = E_OUT_OF_MEMORY,
271                            E_OUT_OF_MEMORY, "[%s] Memory Allocation  Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
272                                 pAdtsHeader = GetHeaderN(__pCodecCtx->sample_rate,__pCodecCtx->channels,srcBufSize,0);
273                 if (pAdtsHeader)
274                 {
275                                         memcpy(pInputData,pAdtsHeader->GetPointer(),ADTS_HEADER_SIZE);
276                                         memcpy(pInputData + ADTS_HEADER_SIZE  ,pSrcBuf,srcBufSize);
277                                         inputPacket.size = srcBufSize + ADTS_HEADER_SIZE;
278                                         inputPacket.data = pInputData;
279                                         res = avcodec_decode_audio3(__pCodecCtx, pOutBuf, &outBufSize, &inputPacket);
280                                         delete pAdtsHeader;
281                                         pAdtsHeader = null;
282                 }
283                                 delete []pInputData;
284                                 pInputData = null;
285         }
286         SysTryCatch(NID_MEDIA,(res > 0 && outBufSize > 0), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
287                             "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
288         SysTryCatch(NID_MEDIA,dstBufSize >= outBufSize, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
289                            "[%s] Memory Allocation  Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
290
291         dstBufUsed = outBufSize; // The decoded audio data size
292         srcBufUsed = res; //Input bytes used
293         if (inputPacket.size == (srcBufSize + ADTS_HEADER_SIZE))
294         {
295                 dstBufUsed = outBufSize; // The decoded audio data size
296                 srcBufUsed = res - ADTS_HEADER_SIZE; //Input bytes used, substract the appended header bytes
297         }
298         else
299         {
300                 dstBufUsed = outBufSize; // The decoded audio data size
301                 srcBufUsed = res; //Input bytes used            
302         }
303
304         if ( pDstBuf != (byte*)pOutBuf)
305         {
306                 memcpy(pDstBuf, pOutBuf, outBufSize);
307         }
308         __decodeCalled = true;
309         return r;
310
311 CATCH:
312         if (res < 0)
313         {
314                 res = av_strerror(res, errStr, errStrLen);
315                 if (!res)
316         {
317                         SysLog(NID_MEDIA, "Error is %s. %d ", errStr, res);
318         }
319         }
320         return r;
321 }
322
323 result
324 _AacDecoder::Probe(const byte* pSrcBuf, const int srcBufLength,
325                                                  Tizen::Media::AudioSampleType& sampleType,
326                                                  Tizen::Media::AudioChannelType& channelType, int& sampleRate)
327 {
328         result r = E_SUCCESS;
329         int res = 0;
330         AVPacket inputPacket;
331         int outBufSize = 0;
332         int16_t* pOutBuf = null;
333
334
335         SysTryCatch(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), r = E_INVALID_STATE, E_INVALID_STATE,
336                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
337         SysTryCatch(NID_MEDIA, (pSrcBuf != null && srcBufLength > 0), r = E_INVALID_ARG, E_INVALID_ARG,
338                            "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
339
340         av_init_packet(&inputPacket);
341
342         inputPacket.data = (uint8_t*) pSrcBuf;
343         inputPacket.size = srcBufLength;
344
345         pOutBuf = (int16_t*)__pOutBuf;
346         outBufSize = DEFAULT_BUFFER_SIZE;
347
348         // Decoding the Audio  packet
349         res = avcodec_decode_audio3(__pCodecCtx, pOutBuf, &outBufSize, &inputPacket);
350         SysTryCatch(NID_MEDIA, (res > 0 && outBufSize > 0) , r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
351                            "[%s] The input data format is not supported ",GetErrorMessage(E_UNSUPPORTED_FORMAT));
352         switch (__pCodecCtx->channels)
353         {
354         case 0:
355                 channelType = AUDIO_CHANNEL_TYPE_NONE;
356         break;
357
358         case 1:
359                 channelType = AUDIO_CHANNEL_TYPE_MONO;
360         break;
361
362         case 2:
363                 channelType = AUDIO_CHANNEL_TYPE_STEREO;
364         break;
365
366         default:
367                 break;
368         }
369
370         switch (__pCodecCtx->sample_fmt)
371         {
372         case AV_SAMPLE_FMT_NONE:
373                 // fall through
374         case AV_SAMPLE_FMT_S32:
375                 // fall through
376         case AV_SAMPLE_FMT_FLT:
377                 // fall through
378         case AV_SAMPLE_FMT_DBL:
379                 // fall through
380         case AV_SAMPLE_FMT_NB:
381                 sampleType = AUDIO_TYPE_NONE;
382         break;
383
384         case AV_SAMPLE_FMT_U8:
385                 sampleType = AUDIO_TYPE_PCM_U8;
386         break;
387
388         case AV_SAMPLE_FMT_S16:
389                 sampleType = AUDIO_TYPE_PCM_S16_LE;
390         break;
391
392         default:
393                 sampleType = AUDIO_TYPE_NONE;
394                 break;
395         }
396
397         sampleRate = __pCodecCtx->sample_rate;
398         __decodeCalled = true;
399         return r;
400
401 CATCH:
402         return r;
403 }
404
405 result
406 _AacDecoder::Reset(void)
407 {
408         result r = E_SUCCESS;
409         SysTryCatch(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), r = E_INVALID_STATE, E_INVALID_STATE,
410                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
411         avcodec_flush_buffers(__pCodecCtx);
412         __decodeCalled = false;
413         return r;
414
415 CATCH:
416         return r;
417 }
418
419 result
420 _AacDecoder::GetValue(MediaPropertyType type, int& value) const
421 {
422         result r = E_SUCCESS;
423         SysTryCatch(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), r = E_INVALID_STATE, E_INVALID_STATE,
424                            "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
425         SysTryCatch(NID_MEDIA, 0 < type, r = E_INVALID_ARG, E_INVALID_ARG,
426                            "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
427         SysTryCatch(NID_MEDIA, __decodeCalled, r = E_INVALID_STATE, E_INVALID_STATE,
428                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
429
430         switch (type)
431         {
432         case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
433                 switch (__pCodecCtx->channels)
434                 {
435                 case 0:
436                         value = AUDIO_CHANNEL_TYPE_NONE;
437                         break;
438
439                 case 1:
440                         value = AUDIO_CHANNEL_TYPE_MONO;
441                         break;
442
443                 case 2:
444                         value = AUDIO_CHANNEL_TYPE_STEREO;
445                         break;
446
447                 default:
448                         break;
449         }
450         break;
451
452         case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
453                 switch (__pCodecCtx->sample_fmt)
454                 {
455                 case AV_SAMPLE_FMT_NONE:
456                         // fall through
457                 case AV_SAMPLE_FMT_S32:
458                         // fall through
459                 case AV_SAMPLE_FMT_FLT:
460                         // fall through
461                 case AV_SAMPLE_FMT_DBL:
462                         // fall through
463                 case AV_SAMPLE_FMT_NB:
464                         value = AUDIO_TYPE_NONE;
465                         break;
466
467                 case AV_SAMPLE_FMT_U8:
468                         value = AUDIO_TYPE_PCM_U8;
469                         break;
470
471                 case AV_SAMPLE_FMT_S16:
472                         value = AUDIO_TYPE_PCM_S16_LE;
473                         break;
474
475                 default:
476                         value = AUDIO_TYPE_NONE;
477                         break;
478                 }
479         break;
480
481         case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
482                 value = __pCodecCtx->sample_rate;
483         break;
484
485         default:
486                 return E_OBJ_NOT_FOUND;
487         break;
488         }
489
490         return r;
491
492 CATCH:
493         return r;
494 }
495
496 result
497 _AacDecoder::GetValue(MediaPropertyType type, float& value) const
498 {
499         result r = E_SUCCESS;
500         SysTryCatch(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), r = E_INVALID_STATE, E_INVALID_STATE,
501                            "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
502         SysTryCatch(NID_MEDIA, type < 0, r = E_INVALID_ARG, E_INVALID_ARG,
503                            "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
504         SysTryCatch(NID_MEDIA, type < MEDIA_PROPERTY_VIDEO_WIDTH || type >= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
505                            r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
506                            "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
507         SysTryCatch(NID_MEDIA, __decodeCalled, r = E_INVALID_STATE, E_INVALID_STATE,
508                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
509
510         return E_OBJ_NOT_FOUND;
511
512 CATCH:
513         return r;
514 }
515
516 Tizen::Base::Collection::IListT<MediaPropertyType>*
517 _AacDecoder::GetSupportedPropertyListN(void) const
518 {
519         result r = E_SUCCESS;
520         ArrayListT<MediaPropertyType>* pPropList = new  (std::nothrow) ArrayListT<MediaPropertyType>;
521
522         SysTryCatch(NID_MEDIA, pPropList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
523                           "[%s] Memory Allocation  Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
524         pPropList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_RATE);
525         pPropList->Add(MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE);
526         pPropList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE);
527         SetLastResult(r);
528         return pPropList;
529
530 CATCH:
531         return null;
532 }
533
534 bool
535 _AacDecoder::IsPropertySupported(MediaPropertyType type) const
536 {
537         result r = E_SUCCESS;
538         SysTryCatch(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), r = E_INVALID_STATE, E_INVALID_STATE,
539                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
540         SysTryCatch(NID_MEDIA, ( type == MEDIA_PROPERTY_AUDIO_SAMPLE_RATE || type == MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE ) ||
541                            (type == MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE ), r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
542                            "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
543         SetLastResult(r);
544         return true;
545
546 CATCH:
547         return false;
548 }
549
550 }} // Tizen::Media