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 av_log_set_level (AV_LOG_QUIET);
85 avcodec_register_all();
87 __pCodec = avcodec_find_decoder(CODEC_ID_AAC);
88 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
89 "[%s] Find Decoder Failed for CODEC_ID_AAC",GetErrorMessage(E_SYSTEM));
91 __pCodecCtx = avcodec_alloc_context3(__pCodec);
92 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
93 "[%s] Context Allcoation Failed",GetErrorMessage(E_SYSTEM));
96 // The initialization values are given in the Hashmap
97 unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
98 if (pMapEnum.get() != null)
100 while (pMapEnum->MoveNext() == E_SUCCESS)
102 pKey = static_cast<Integer*>(pMapEnum->GetKey());
103 pValue = static_cast<Integer*>(pMapEnum->GetValue());
107 value = pValue->ToInt();
110 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
111 SysTryCatch(NID_MEDIA, (value == 0 || value == 1 || value == 2), r = E_OUT_OF_RANGE,
112 E_OUT_OF_RANGE, "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
113 __pCodecCtx->channels = value;
116 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
117 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
118 "[%s] Invalid argument: %d", GetErrorMessage(E_OUT_OF_RANGE), value);
119 __pCodecCtx->sample_rate = value;
122 case MEDIA_PROPERTY_AUDIO_BIT_RATE:
123 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
124 "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
125 __pCodecCtx->bit_rate = value;
136 __pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
137 res = avcodec_open2(__pCodecCtx, __pCodec, null);
138 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
139 "[%s] AVCODEC Codec Open Failed for CODEC_ID_AAC",GetErrorMessage(E_SYSTEM));
141 // AVCodecContext parameters
142 if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
144 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
147 __pCodecCtx->debug_mv = 0; //set by user
148 __pCodecCtx->debug = 0; //set by user
149 __pCodecCtx->workaround_bugs = 1; //set by user
150 __pCodecCtx->extradata_size = 0;
152 __pOutBuf = new (std::nothrow) byte[DEFAULT_BUFFER_SIZE];
153 SysTryCatch(NID_MEDIA, __pOutBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
154 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
159 if (__pCodecCtx != null)
161 avcodec_close(__pCodecCtx);
162 av_free(__pCodecCtx);
170 _AacDecoder::GetHeaderN(int sampleRate, int channels, int size, int pce_size)
172 result r = E_SUCCESS;
173 unique_ptr<ByteBuffer> pBuf(new (std::nothrow) ByteBuffer());
175 SysTryReturn(NID_MEDIA, pBuf.get() != null, null, E_OUT_OF_MEMORY, "new ByteBuffer() failed");
177 r = pBuf->Construct(ADTS_HEADER_SIZE);
178 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] ByteBuffer.Construct(%d) failed", GetErrorMessage(r), ADTS_HEADER_SIZE);
180 _BitWriter bw((byte*)pBuf->GetPointer(),pBuf->GetCapacity());
181 int sampleRateIndex = 0x0b;
182 int count = (int)(sizeof(_AAC_SAMPLE_RATE_INDEX)/sizeof(_AAC_SAMPLE_RATE_INDEX[0]));
183 for (int i = 0; i < count; i++)
185 if (_AAC_SAMPLE_RATE_INDEX[i] == sampleRate)
193 bw.PutBits(12, 0xfff); // syncword
194 bw.PutBits(1, 0); // id
195 bw.PutBits(2, 0); // layer
196 bw.PutBits(1, 1); // protection
197 bw.PutBits(2, 1); // profile : LC: 01
198 bw.PutBits(4, sampleRateIndex); // sample rate index
199 bw.PutBits(1, 0); // private
200 bw.PutBits(3, channels); // channel
201 bw.PutBits(1, 0); // original copy
202 bw.PutBits(1, 0); // home
205 bw.PutBits(1, 0); // copyright id bit
206 bw.PutBits(1, 0); // copyright id start
207 bw.PutBits(13, ADTS_HEADER_SIZE+size+pce_size); // aac frame length
208 bw.PutBits(11, 0x7ff); // buffer fullness
209 bw.PutBits(2, 0); // number of raw data blocks in frame
211 pBuf->SetPosition(0);
212 r = pBuf->SetLimit(ADTS_HEADER_SIZE);
213 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] ByteBuffer.SetLimit(%d) failed", GetErrorMessage(r), ADTS_HEADER_SIZE);
215 return pBuf.release();
219 _AacDecoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
220 byte* pDstBuf, int dstBufSize, int& dstBufUsed)
223 AVPacket inputPacket;
225 unique_ptr<AVFrame, _FfmpegDeleter> pOutFrame(avcodec_alloc_frame(), ffmpegDeleter);
228 SysTryReturnResult(NID_MEDIA, __pCodecCtx != null, E_INVALID_STATE, "The instance is in invalid state");
229 SysTryReturnResult(NID_MEDIA, (pSrcBuf != null && pDstBuf != null && srcBufSize > 0 && dstBufSize > 0),
230 E_INVALID_ARG, "Invalid argument. pSrcBuf(0x%x), srcBufSize(%d), pDstBuf(0x%x), dstBufSize",
231 pSrcBuf, srcBufSize, pDstBuf, dstBufSize);
232 SysTryReturnResult(NID_MEDIA, pOutFrame.get() != null, E_OUT_OF_MEMORY, "avcodec_alloc_frame() failed");
234 av_init_packet(&inputPacket);
235 inputPacket.size = srcBufSize;
236 inputPacket.data = (uint8_t*)pSrcBuf;
238 // Decoding the Audio packet
239 res = avcodec_decode_audio4(__pCodecCtx, pOutFrame.get(), &gotFrame, &inputPacket);
240 // add adts header and try to decode
241 if ( res < 0 && !((pSrcBuf[0] == 0xff) && ((pSrcBuf[1] & 0xf6) == 0xf0)))
243 unique_ptr<uint8_t[]> pInputData(new (std::nothrow) uint8_t[srcBufSize + ADTS_HEADER_SIZE]);
244 unique_ptr<ByteBuffer> pAdtsHeader(GetHeaderN(__pCodecCtx->sample_rate,__pCodecCtx->channels, srcBufSize, 0));
246 SysTryReturnResult(NID_MEDIA, pInputData.get() != null, E_OUT_OF_MEMORY, "new byte[%d] failed", srcBufSize + ADTS_HEADER_SIZE);
247 SysTryReturnResult(NID_MEDIA, pAdtsHeader.get() != null, E_OUT_OF_MEMORY,
248 "ADTS header generate failed:%d %d %d", __pCodecCtx->sample_rate,__pCodecCtx->channels, srcBufSize);
250 memcpy(pInputData.get(),pAdtsHeader->GetPointer(), ADTS_HEADER_SIZE);
251 memcpy(pInputData.get() + ADTS_HEADER_SIZE, pSrcBuf, srcBufSize);
252 inputPacket.size = srcBufSize + ADTS_HEADER_SIZE;
253 inputPacket.data = pInputData.get();
254 res = avcodec_decode_audio4(__pCodecCtx, pOutFrame.get(), &gotFrame, &inputPacket);
257 SysTryReturnResult(NID_MEDIA, (res > 0 && gotFrame > 0), E_UNSUPPORTED_FORMAT, "decode audio failed:%d", res);
259 if (inputPacket.size == (srcBufSize + ADTS_HEADER_SIZE))
261 dstBufUsed = outBufSize; // The decoded audio data size
262 srcBufUsed = res - ADTS_HEADER_SIZE; //Input bytes used, substract the appended header bytes
266 dstBufUsed = outBufSize; // The decoded audio data size
267 srcBufUsed = res; //Input bytes used
270 outBufSize = av_samples_get_buffer_size(NULL, __pCodecCtx->channels, pOutFrame->nb_samples, __pCodecCtx->sample_fmt, 1);
272 SysTryReturnResult(NID_MEDIA, dstBufSize >= outBufSize, E_OUT_OF_MEMORY, "pDstBuf(%d) is smaller than decoded data(%d)", dstBufSize, outBufSize);
274 dstBufUsed = outBufSize; // The decoded audio data size
275 memcpy(pDstBuf, pOutFrame->data[0], outBufSize);
277 __decodeCalled = true;
283 _AacDecoder::Probe(const byte* pSrcBuf, const int srcBufLength,
284 Tizen::Media::AudioSampleType& sampleType,
285 Tizen::Media::AudioChannelType& channelType, int& sampleRate)
287 result r = E_SUCCESS;
288 unique_ptr<byte[]> pDstBuf(new (std::nothrow) byte[DEFAULT_BUFFER_SIZE]);
292 SysTryReturnResult(NID_MEDIA, pDstBuf.get() != null, E_OUT_OF_MEMORY, "new byte[%d] failed", DEFAULT_BUFFER_SIZE);
294 r = Decode(pSrcBuf, srcBufLength, srcBufUsed, pDstBuf.get(), DEFAULT_BUFFER_SIZE, dstBufUsed);
295 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Decode() failed", GetErrorMessage(r));
297 channelType = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
298 sampleType = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
299 sampleRate = __pCodecCtx->sample_rate;
301 SysTryReturnResult(NID_MEDIA, channelType != AUDIO_CHANNEL_TYPE_NONE, E_UNSUPPORTED_FORMAT, "Unknown channel type:%d", __pCodecCtx->channels);
302 SysTryReturnResult(NID_MEDIA, sampleType != AUDIO_TYPE_NONE, E_UNSUPPORTED_FORMAT, "Unknown sample type:%d", __pCodecCtx->sample_fmt);
303 SysTryReturnResult(NID_MEDIA, sampleRate > 0, E_UNSUPPORTED_FORMAT, "Unknown sample rate:%d", __pCodecCtx->sample_rate);
309 _AacDecoder::Reset(void)
311 SysTryReturnResult(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), E_INVALID_STATE, "The instance is in invalid state");
312 avcodec_flush_buffers(__pCodecCtx);
313 __decodeCalled = false;
319 _AacDecoder::GetValue(MediaPropertyType type, int& value) const
321 SysTryReturnResult(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), E_INVALID_STATE, "The instance is in invalid state");
322 SysTryReturnResult(NID_MEDIA, 0 < type, E_INVALID_ARG, "Invalid argument: type=%d", type);
323 SysTryReturnResult(NID_MEDIA, __decodeCalled, E_INVALID_STATE, "No decoding or probing has performed.");
327 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
328 value = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
331 case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
332 value = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
335 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
336 value = __pCodecCtx->sample_rate;
340 return E_OBJ_NOT_FOUND;
348 _AacDecoder::GetValue(MediaPropertyType type, float& value) const
350 SysTryReturnResult(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), E_INVALID_STATE, "The instance is in invalid state");
351 SysTryReturnResult(NID_MEDIA, 0 < type, E_INVALID_ARG, "Invalid argument: type=%d", type);
352 SysTryReturnResult(NID_MEDIA, __decodeCalled, E_INVALID_STATE, "No decoding or probing has performed.");
354 return E_OBJ_NOT_FOUND;
357 Tizen::Base::Collection::IListT<MediaPropertyType>*
358 _AacDecoder::GetSupportedPropertyListN(void) const
360 result r = E_SUCCESS;
361 ArrayListT<MediaPropertyType>* pPropList = new (std::nothrow) ArrayListT<MediaPropertyType>;
363 SysTryCatch(NID_MEDIA, pPropList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
364 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
365 pPropList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_RATE);
366 pPropList->Add(MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE);
367 pPropList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE);
376 _AacDecoder::IsPropertySupported(MediaPropertyType type) const
378 result r = E_SUCCESS;
379 SysTryCatch(NID_MEDIA, (__pCodecCtx != null && __pCodec != null), r = E_INVALID_STATE, E_INVALID_STATE,
380 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
381 SysTryCatch(NID_MEDIA, ( type == MEDIA_PROPERTY_AUDIO_SAMPLE_RATE || type == MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE ) ||
382 (type == MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE ), r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
383 "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));