2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
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"
29 using namespace Tizen::Base;
30 using namespace Tizen::Io;
31 using namespace Tizen::Base::Collection;
33 namespace Tizen { namespace Media
36 #define ADTS_HEADER_SIZE 7
38 static const int _AAC_SAMPLE_RATE_INDEX[] = {
39 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 };
42 _AacDecoder_CreateInstance(void)
44 return new (std::nothrow) _AacDecoder();
47 _AacDecoder::_AacDecoder(void)
51 __decodeCalled = false;
55 _AacDecoder::~_AacDecoder(void)
57 if (__pCodecCtx != null)
59 avcodec_close(__pCodecCtx);
64 if (__pOutBuf != null)
71 _AacDecoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
76 Integer* pValue = null;
80 SysAssertf((__pCodecCtx == null && __pCodec == null), " Already Constructed .");
82 avcodec_register_all();
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));
93 // The initialization values are given in the Hashmap
94 std::unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
95 if (pMapEnum.get() != null)
97 while (pMapEnum.get()->MoveNext() == E_SUCCESS)
99 pKey = static_cast<Integer*>(pMapEnum.get()->GetKey());
100 pValue = static_cast<Integer*>(pMapEnum.get()->GetValue());
104 value = pValue->ToInt();
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;
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;
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;
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));
138 // AVCodecContext parameters
139 if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
141 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
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;
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));
157 if (__pCodecCtx != null)
159 avcodec_close(__pCodecCtx);
160 av_free(__pCodecCtx);
168 _AacDecoder::GetHeaderN(int sampleRate, int channels, int size, int pce_size)
170 ByteBuffer* pBuf = null;
171 result r = E_SUCCESS;
173 pBuf = new (std::nothrow) ByteBuffer();
180 r = pBuf->Construct(ADTS_HEADER_SIZE);
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++)
192 if (_AAC_SAMPLE_RATE_INDEX[i] == sampleRate)
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
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
218 pBuf->SetPosition(0);
219 r = pBuf->SetLimit(ADTS_HEADER_SIZE);
230 _AacDecoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
231 byte* pDstBuf, int dstBufSize, int& dstBufUsed)
233 result r = E_SUCCESS;
235 AVPacket inputPacket;
237 int16_t* pOutBuf = null;
239 char errStr[errStrLen];
240 uint8_t* pInputData = null;
241 const ByteBuffer* pAdtsHeader = null;
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));
249 av_init_packet(&inputPacket);
250 inputPacket.size = srcBufSize;
251 inputPacket.data = (uint8_t*)pSrcBuf;
253 if (dstBufSize >= DEFAULT_BUFFER_SIZE)
255 pOutBuf = (int16_t*)pDstBuf;
256 outBufSize = dstBufSize;
260 pOutBuf = (int16_t*)__pOutBuf;
261 outBufSize = DEFAULT_BUFFER_SIZE;
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)))
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);
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);
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));
291 dstBufUsed = outBufSize; // The decoded audio data size
292 srcBufUsed = res; //Input bytes used
293 if (inputPacket.size == (srcBufSize + ADTS_HEADER_SIZE))
295 dstBufUsed = outBufSize; // The decoded audio data size
296 srcBufUsed = res - ADTS_HEADER_SIZE; //Input bytes used, substract the appended header bytes
300 dstBufUsed = outBufSize; // The decoded audio data size
301 srcBufUsed = res; //Input bytes used
304 if ( pDstBuf != (byte*)pOutBuf)
306 memcpy(pDstBuf, pOutBuf, outBufSize);
308 __decodeCalled = true;
314 res = av_strerror(res, errStr, errStrLen);
317 SysLog(NID_MEDIA, "Error is %s. %d ", errStr, res);
324 _AacDecoder::Probe(const byte* pSrcBuf, const int srcBufLength,
325 Tizen::Media::AudioSampleType& sampleType,
326 Tizen::Media::AudioChannelType& channelType, int& sampleRate)
328 result r = E_SUCCESS;
330 AVPacket inputPacket;
332 int16_t* pOutBuf = null;
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));
340 av_init_packet(&inputPacket);
342 inputPacket.data = (uint8_t*) pSrcBuf;
343 inputPacket.size = srcBufLength;
345 pOutBuf = (int16_t*)__pOutBuf;
346 outBufSize = DEFAULT_BUFFER_SIZE;
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)
355 channelType = AUDIO_CHANNEL_TYPE_NONE;
359 channelType = AUDIO_CHANNEL_TYPE_MONO;
363 channelType = AUDIO_CHANNEL_TYPE_STEREO;
370 switch (__pCodecCtx->sample_fmt)
372 case AV_SAMPLE_FMT_NONE:
374 case AV_SAMPLE_FMT_S32:
376 case AV_SAMPLE_FMT_FLT:
378 case AV_SAMPLE_FMT_DBL:
380 case AV_SAMPLE_FMT_NB:
381 sampleType = AUDIO_TYPE_NONE;
384 case AV_SAMPLE_FMT_U8:
385 sampleType = AUDIO_TYPE_PCM_U8;
388 case AV_SAMPLE_FMT_S16:
389 sampleType = AUDIO_TYPE_PCM_S16_LE;
393 sampleType = AUDIO_TYPE_NONE;
397 sampleRate = __pCodecCtx->sample_rate;
398 __decodeCalled = true;
406 _AacDecoder::Reset(void)
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;
420 _AacDecoder::GetValue(MediaPropertyType type, int& value) const
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));
432 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
433 switch (__pCodecCtx->channels)
436 value = AUDIO_CHANNEL_TYPE_NONE;
440 value = AUDIO_CHANNEL_TYPE_MONO;
444 value = AUDIO_CHANNEL_TYPE_STEREO;
452 case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
453 switch (__pCodecCtx->sample_fmt)
455 case AV_SAMPLE_FMT_NONE:
457 case AV_SAMPLE_FMT_S32:
459 case AV_SAMPLE_FMT_FLT:
461 case AV_SAMPLE_FMT_DBL:
463 case AV_SAMPLE_FMT_NB:
464 value = AUDIO_TYPE_NONE;
467 case AV_SAMPLE_FMT_U8:
468 value = AUDIO_TYPE_PCM_U8;
471 case AV_SAMPLE_FMT_S16:
472 value = AUDIO_TYPE_PCM_S16_LE;
476 value = AUDIO_TYPE_NONE;
481 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
482 value = __pCodecCtx->sample_rate;
486 return E_OBJ_NOT_FOUND;
497 _AacDecoder::GetValue(MediaPropertyType type, float& value) const
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));
510 return E_OBJ_NOT_FOUND;
516 Tizen::Base::Collection::IListT<MediaPropertyType>*
517 _AacDecoder::GetSupportedPropertyListN(void) const
519 result r = E_SUCCESS;
520 ArrayListT<MediaPropertyType>* pPropList = new (std::nothrow) ArrayListT<MediaPropertyType>;
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);
535 _AacDecoder::IsPropertySupported(MediaPropertyType type) const
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));