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_FfmpegUtil.h"
26 #include "FMedia_IAudioDecoder.h"
27 #include "FMedia_AacDecoder.h"
28 #include "FMedia_BitWriter.h"
31 using namespace Tizen::Base;
32 using namespace Tizen::Io;
33 using namespace Tizen::Base::Collection;
35 namespace Tizen { namespace Media
38 #define ADTS_HEADER_SIZE 7
40 static const int _AAC_SAMPLE_RATE_INDEX[] = {
41 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 };
44 _AacDecoder_CreateInstance(void)
46 return new (std::nothrow) _AacDecoder();
49 _AacDecoder::_AacDecoder(void)
53 __decodeCalled = false;
57 _AacDecoder::~_AacDecoder(void)
59 if (__pCodecCtx != null)
61 avcodec_close(__pCodecCtx);
66 if (__pOutBuf != null)
73 _AacDecoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
78 Integer* pValue = null;
82 SysAssertf((__pCodecCtx == null && __pCodec == null), " Already Constructed .");
84 avcodec_register_all();
86 __pCodec = avcodec_find_decoder(CODEC_ID_AAC);
87 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
88 "[%s] Find Decoder Failed for CODEC_ID_AAC",GetErrorMessage(E_SYSTEM));
90 __pCodecCtx = avcodec_alloc_context3(__pCodec);
91 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
92 "[%s] Context Allcoation Failed",GetErrorMessage(E_SYSTEM));
95 // The initialization values are given in the Hashmap
96 unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
97 if (pMapEnum.get() != null)
99 while (pMapEnum->MoveNext() == E_SUCCESS)
101 pKey = static_cast<Integer*>(pMapEnum->GetKey());
102 pValue = static_cast<Integer*>(pMapEnum->GetValue());
106 value = pValue->ToInt();
109 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
110 SysTryCatch(NID_MEDIA, (value == 0 || value == 1 || value == 2), r = E_OUT_OF_RANGE,
111 E_OUT_OF_RANGE, "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
112 __pCodecCtx->channels = value;
115 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
116 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
117 "[%s] Invalid argument: %d", GetErrorMessage(E_OUT_OF_RANGE), value);
118 __pCodecCtx->sample_rate = value;
121 case MEDIA_PROPERTY_AUDIO_BIT_RATE:
122 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
123 "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
124 __pCodecCtx->bit_rate = value;
135 __pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
136 res = avcodec_open2(__pCodecCtx, __pCodec, null);
137 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
138 "[%s] AVCODEC Codec Open Failed for CODEC_ID_AAC",GetErrorMessage(E_SYSTEM));
140 // AVCodecContext parameters
141 if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
143 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
146 __pCodecCtx->debug_mv = 0; //set by user
147 __pCodecCtx->debug = 0; //set by user
148 __pCodecCtx->workaround_bugs = 1; //set by user
149 __pCodecCtx->extradata_size = 0;
151 __pOutBuf = new (std::nothrow) byte[DEFAULT_BUFFER_SIZE];
152 SysTryCatch(NID_MEDIA, __pOutBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
153 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
158 if (__pCodecCtx != null)
160 avcodec_close(__pCodecCtx);
161 av_free(__pCodecCtx);
169 _AacDecoder::GetHeaderN(int sampleRate, int channels, int size, int pce_size)
171 result r = E_SUCCESS;
172 unique_ptr<ByteBuffer> pBuf(new (std::nothrow) ByteBuffer());
174 SysTryReturn(NID_MEDIA, pBuf.get() != null, null, E_OUT_OF_MEMORY, "new ByteBuffer() failed");
176 r = pBuf->Construct(ADTS_HEADER_SIZE);
177 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] ByteBuffer.Construct(%d) failed", GetErrorMessage(r), ADTS_HEADER_SIZE);
179 _BitWriter bw((byte*)pBuf->GetPointer(),pBuf->GetCapacity());
180 int sampleRateIndex = 0x0b;
181 int count = (int)(sizeof(_AAC_SAMPLE_RATE_INDEX)/sizeof(_AAC_SAMPLE_RATE_INDEX[0]));
182 for (int i = 0; i < count; i++)
184 if (_AAC_SAMPLE_RATE_INDEX[i] == sampleRate)
192 bw.PutBits(12, 0xfff); // syncword
193 bw.PutBits(1, 0); // id
194 bw.PutBits(2, 0); // layer
195 bw.PutBits(1, 1); // protection
196 bw.PutBits(2, 1); // profile : LC: 01
197 bw.PutBits(4, sampleRateIndex); // sample rate index
198 bw.PutBits(1, 0); // private
199 bw.PutBits(3, channels); // channel
200 bw.PutBits(1, 0); // original copy
201 bw.PutBits(1, 0); // home
204 bw.PutBits(1, 0); // copyright id bit
205 bw.PutBits(1, 0); // copyright id start
206 bw.PutBits(13, ADTS_HEADER_SIZE+size+pce_size); // aac frame length
207 bw.PutBits(11, 0x7ff); // buffer fullness
208 bw.PutBits(2, 0); // number of raw data blocks in frame
210 pBuf->SetPosition(0);
211 r = pBuf->SetLimit(ADTS_HEADER_SIZE);
212 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] ByteBuffer.SetLimit(%d) failed", GetErrorMessage(r), ADTS_HEADER_SIZE);
214 return pBuf.release();
218 _AacDecoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
219 byte* pDstBuf, int dstBufSize, int& dstBufUsed)
222 AVPacket inputPacket;
224 unique_ptr<AVFrame, _FfmpegDeleter> pOutFrame(avcodec_alloc_frame(), ffmpegDeleter);
227 SysTryReturnResult(NID_MEDIA, __pCodecCtx != null, E_INVALID_STATE, "The instance is in invalid state");
228 SysTryReturnResult(NID_MEDIA, (pSrcBuf != null && pDstBuf != null && srcBufSize > 0 && dstBufSize > 0),
229 E_INVALID_ARG, "Invalid argument. pSrcBuf(0x%x), srcBufSize(%d), pDstBuf(0x%x), dstBufSize",
230 pSrcBuf, srcBufSize, pDstBuf, dstBufSize);
231 SysTryReturnResult(NID_MEDIA, pOutFrame.get() != null, E_OUT_OF_MEMORY, "avcodec_alloc_frame() failed");
233 av_init_packet(&inputPacket);
234 inputPacket.size = srcBufSize;
235 inputPacket.data = (uint8_t*)pSrcBuf;
237 // Decoding the Audio packet
238 res = avcodec_decode_audio4(__pCodecCtx, pOutFrame.get(), &gotFrame, &inputPacket);
239 // add adts header and try to decode
240 if ( res < 0 && !((pSrcBuf[0] == 0xff) && ((pSrcBuf[1] & 0xf6) == 0xf0)))
242 unique_ptr<uint8_t[]> pInputData(new (std::nothrow) uint8_t[srcBufSize + ADTS_HEADER_SIZE]);
243 unique_ptr<ByteBuffer> pAdtsHeader(GetHeaderN(__pCodecCtx->sample_rate,__pCodecCtx->channels, srcBufSize, 0));
245 SysTryReturnResult(NID_MEDIA, pInputData.get() != null, E_OUT_OF_MEMORY, "new byte[%d] failed", srcBufSize + ADTS_HEADER_SIZE);
246 SysTryReturnResult(NID_MEDIA, pAdtsHeader.get() != null, E_OUT_OF_MEMORY,
247 "ADTS header generate failed:%d %d %d", __pCodecCtx->sample_rate,__pCodecCtx->channels, srcBufSize);
249 memcpy(pInputData.get(),pAdtsHeader->GetPointer(), ADTS_HEADER_SIZE);
250 memcpy(pInputData.get() + ADTS_HEADER_SIZE, pSrcBuf, srcBufSize);
251 inputPacket.size = srcBufSize + ADTS_HEADER_SIZE;
252 inputPacket.data = pInputData.get();
253 res = avcodec_decode_audio4(__pCodecCtx, pOutFrame.get(), &gotFrame, &inputPacket);
256 SysTryReturnResult(NID_MEDIA, (res > 0 && gotFrame > 0), E_UNSUPPORTED_FORMAT, "decode audio failed:%d", res);
258 if (inputPacket.size == (srcBufSize + ADTS_HEADER_SIZE))
260 dstBufUsed = outBufSize; // The decoded audio data size
261 srcBufUsed = res - ADTS_HEADER_SIZE; //Input bytes used, substract the appended header bytes
265 dstBufUsed = outBufSize; // The decoded audio data size
266 srcBufUsed = res; //Input bytes used
269 outBufSize = av_samples_get_buffer_size(NULL, __pCodecCtx->channels, pOutFrame->nb_samples, __pCodecCtx->sample_fmt, 1);
271 SysTryReturnResult(NID_MEDIA, dstBufSize >= outBufSize, E_OUT_OF_MEMORY, "pDstBuf(%d) is smaller than decoded data(%d)", dstBufSize, outBufSize);
273 dstBufUsed = outBufSize; // The decoded audio data size
274 memcpy(pDstBuf, pOutFrame->data[0], outBufSize);
276 __decodeCalled = true;
282 _AacDecoder::Probe(const byte* pSrcBuf, const int srcBufLength,
283 Tizen::Media::AudioSampleType& sampleType,
284 Tizen::Media::AudioChannelType& channelType, int& sampleRate)
286 result r = E_SUCCESS;
287 unique_ptr<byte[]> pDstBuf(new (std::nothrow) byte[DEFAULT_BUFFER_SIZE]);
291 SysTryReturnResult(NID_MEDIA, pDstBuf.get() != null, E_OUT_OF_MEMORY, "new byte[%d] failed", DEFAULT_BUFFER_SIZE);
293 r = Decode(pSrcBuf, srcBufLength, srcBufUsed, pDstBuf.get(), DEFAULT_BUFFER_SIZE, dstBufUsed);
294 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Decode() failed", GetErrorMessage(r));
296 channelType = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
297 sampleType = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
298 sampleRate = __pCodecCtx->sample_rate;
300 SysTryReturnResult(NID_MEDIA, channelType != AUDIO_CHANNEL_TYPE_NONE, E_UNSUPPORTED_FORMAT, "Unknown channel type:%d", __pCodecCtx->channels);
301 SysTryReturnResult(NID_MEDIA, sampleType != AUDIO_TYPE_NONE, E_UNSUPPORTED_FORMAT, "Unknown sample type:%d", __pCodecCtx->sample_fmt);
302 SysTryReturnResult(NID_MEDIA, sampleRate > 0, E_UNSUPPORTED_FORMAT, "Unknown sample rate:%d", __pCodecCtx->sample_rate);
308 _AacDecoder::Reset(void)
310 SysTryReturnResult(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), E_INVALID_STATE, "The instance is in invalid state");
311 avcodec_flush_buffers(__pCodecCtx);
312 __decodeCalled = false;
318 _AacDecoder::GetValue(MediaPropertyType type, int& value) const
320 SysTryReturnResult(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), E_INVALID_STATE, "The instance is in invalid state");
321 SysTryReturnResult(NID_MEDIA, 0 < type, E_INVALID_ARG, "Invalid argument: type=%d", type);
322 SysTryReturnResult(NID_MEDIA, __decodeCalled, E_INVALID_STATE, "No decoding or probing has performed.");
326 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
327 value = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
330 case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
331 value = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
334 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
335 value = __pCodecCtx->sample_rate;
339 return E_OBJ_NOT_FOUND;
347 _AacDecoder::GetValue(MediaPropertyType type, float& value) const
349 SysTryReturnResult(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), E_INVALID_STATE, "The instance is in invalid state");
350 SysTryReturnResult(NID_MEDIA, 0 < type, E_INVALID_ARG, "Invalid argument: type=%d", type);
351 SysTryReturnResult(NID_MEDIA, __decodeCalled, E_INVALID_STATE, "No decoding or probing has performed.");
353 return E_OBJ_NOT_FOUND;
356 Tizen::Base::Collection::IListT<MediaPropertyType>*
357 _AacDecoder::GetSupportedPropertyListN(void) const
359 result r = E_SUCCESS;
360 ArrayListT<MediaPropertyType>* pPropList = new (std::nothrow) ArrayListT<MediaPropertyType>;
362 SysTryCatch(NID_MEDIA, pPropList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
363 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
364 pPropList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_RATE);
365 pPropList->Add(MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE);
366 pPropList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE);
375 _AacDecoder::IsPropertySupported(MediaPropertyType type) const
377 result r = E_SUCCESS;
378 SysTryCatch(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), r = E_INVALID_STATE, E_INVALID_STATE,
379 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
380 SysTryCatch(NID_MEDIA, ( type == MEDIA_PROPERTY_AUDIO_SAMPLE_RATE || type == MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE ) ||
381 (type == MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE ), r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
382 "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));