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.
19 #include <unique_ptr.h>
20 #include <FBaseColArrayListT.h>
21 #include <FBaseColHashMap.h>
22 #include <FMediaTypes.h>
23 #include <FMediaAudioTypes.h>
24 #include <FBaseSysLog.h>
25 #include "FMedia_Ffmpeg.h"
26 #include "FMedia_FfmpegUtil.h"
27 #include "FMedia_IAudioDecoder.h"
28 #include "FMedia_Mp3Decoder.h"
31 using namespace Tizen::Base;
32 using namespace Tizen::Io;
33 using namespace Tizen::Base::Collection;
35 namespace Tizen { namespace Media
39 _Mp3Decoder_CreateInstance(void)
41 return new (std::nothrow) _Mp3Decoder();
44 _Mp3Decoder::_Mp3Decoder(void)
48 __decodeCalled = false;
52 _Mp3Decoder::~_Mp3Decoder(void)
54 if (__pCodecCtx != null)
56 avcodec_close(__pCodecCtx);
59 if (__pOutBuf != null)
66 _Mp3Decoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
71 SysAssertf((__pCodecCtx == null && __pCodec == null), " Already Constructed .");
\r
73 avcodec_register_all();
75 __pCodec = avcodec_find_decoder(CODEC_ID_MP3);
76 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
77 "[%s] AVCODEC Find Decoder Failed for CODEC_ID_MP3",GetErrorMessage(E_SYSTEM));
79 __pCodecCtx = avcodec_alloc_context3(__pCodec);
80 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
81 "[%s] AVCODEC Context Allcoation Failed",GetErrorMessage(E_SYSTEM));
\r
83 res = avcodec_open2(__pCodecCtx, __pCodec, null);
84 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
85 "[%s] AVCODEC Codec Open Failed for CODEC_ID_MP3",GetErrorMessage(E_SYSTEM));
\r
87 // AVCodecContext parameters
88 if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
90 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
93 __pCodecCtx->debug_mv = 0; //set by user
94 __pCodecCtx->debug = 0; //set by user
95 __pCodecCtx->workaround_bugs = 1; //set by user
96 __pCodecCtx->lowres = 0; //set by user
97 __pCodecCtx->skip_frame = AVDISCARD_DEFAULT; //set by user
98 __pCodecCtx->skip_idct = AVDISCARD_DEFAULT; //set by user
99 __pCodecCtx->skip_loop_filter = AVDISCARD_DEFAULT; //set by user
101 __pOutBuf = new (std::nothrow) byte[_MIN_OUT_BUFFER_SIZE];
102 SysTryCatch(NID_MEDIA, __pOutBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
103 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
108 if (__pCodecCtx != null)
110 avcodec_close(__pCodecCtx);
111 av_free(__pCodecCtx);
115 if (__pOutBuf != null)
124 _Mp3Decoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
125 byte* pDstBuf, int dstBufSize, int& dstBufUsed)
128 AVPacket inputPacket;
130 bool hasSyncBits = false;
131 int srcBytesSkipped = 0;
132 unique_ptr<AVFrame, _FfmpegDeleter> pOutFrame(avcodec_alloc_frame(), ffmpegDeleter);
135 SysTryReturnResult(NID_MEDIA, __pCodecCtx != null, E_INVALID_STATE, "The instance is in invalid state");
\r
136 SysTryReturnResult(NID_MEDIA, pSrcBuf != null && pDstBuf != null && srcBufSize > 0 && dstBufSize > 0, E_INVALID_ARG,
137 "Invalid argument: pSrcBuf(0x%x), srcBufSize(%d), pDstBuf(0x%x), dstBufSize(%d)",
138 pSrcBuf, srcBufSize, pDstBuf, dstBufSize);
\r
139 SysTryReturnResult(NID_MEDIA, pOutFrame.get() != null, E_OUT_OF_MEMORY, "avcodec_alloc_frame() failed");
141 av_init_packet(&inputPacket);
143 // check this routines is required
144 for (int i = 0; i < srcBufSize - 1; i++)
146 if ((pSrcBuf[i] == 0xff) && ((pSrcBuf[i + 1] == 0xfb) || (pSrcBuf[i + 1] == 0xf3)))
149 inputPacket.size = srcBufSize - i;
150 inputPacket.data = (uint8_t*)pSrcBuf + i;
156 SysTryReturnResult(NID_MEDIA, hasSyncBits, E_UNSUPPORTED_FORMAT, "The input data format is not supported");
\r
158 res = avcodec_decode_audio4(__pCodecCtx, pOutFrame.get(), &gotFrame, &inputPacket);
160 SysTryReturnResult(NID_MEDIA, res > 0, E_UNSUPPORTED_FORMAT, "decode audio failed:%d", res);
164 outBufSize = av_samples_get_buffer_size(NULL, __pCodecCtx->channels, pOutFrame->nb_samples, __pCodecCtx->sample_fmt, 1);
166 SysTryReturnResult(NID_MEDIA, dstBufSize >= outBufSize, E_OUT_OF_MEMORY, "pDstBuf(%d) is smaller than decoded data(%d)", dstBufSize, outBufSize);
168 dstBufUsed = outBufSize; // The decoded audio data size
169 memcpy(pDstBuf, pOutFrame->data[0], outBufSize);
170 __decodeCalled = true;
177 srcBufUsed = res + srcBytesSkipped; // input bytes used
183 _Mp3Decoder::Probe(const byte* pSrcBuf, const int srcBufSize,
184 AudioSampleType& sampleType, AudioChannelType& channelType, int& sampleRate)
186 result r = E_SUCCESS;
191 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
192 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
193 SysTryCatch(NID_MEDIA, pSrcBuf != null && srcBufSize > 0, r = E_INVALID_ARG, E_INVALID_ARG,
194 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
196 r = Decode(pSrcBuf, srcBufSize, srcBufUsed, __pOutBuf, _MIN_OUT_BUFFER_SIZE, dstBufUsed);
198 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Decode failed", GetErrorMessage(r));
200 channelType = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
201 sampleType = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
202 sampleRate = __pCodecCtx->sample_rate;
204 SetLastResult(E_SUCCESS);
212 _Mp3Decoder::Reset(void)
214 result r = E_SUCCESS;
216 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
217 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
219 avcodec_flush_buffers(__pCodecCtx);
221 __decodeCalled = false;
222 SetLastResult(E_SUCCESS);
230 _Mp3Decoder::GetValue(MediaPropertyType type, int& value) const
232 result r = E_SUCCESS;
234 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
235 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
236 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
237 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
238 SysTryCatch(NID_MEDIA, __decodeCalled, r = E_INVALID_STATE, E_INVALID_STATE,
239 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
243 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
244 value = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
247 case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
248 value = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
251 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
252 value = __pCodecCtx->sample_rate;
255 case MEDIA_PROPERTY_AUDIO_BIT_RATE:
256 value = __pCodecCtx->bit_rate;
271 _Mp3Decoder::GetValue(MediaPropertyType type, float& value) const
273 result r = E_SUCCESS;
274 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
275 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
276 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
277 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
278 SysTryCatch(NID_MEDIA, __decodeCalled, r = E_INVALID_STATE, E_INVALID_STATE,
279 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
281 return E_OBJ_NOT_FOUND;
287 Tizen::Base::Collection::IListT<MediaPropertyType>*
288 _Mp3Decoder::GetSupportedPropertyListN(void) const
290 result r = E_SUCCESS;
291 ArrayListT<MediaPropertyType>* pList = new (std::nothrow) ArrayListT<MediaPropertyType>;
293 SysTryCatch(NID_MEDIA, pList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
294 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
295 pList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_RATE);
296 pList->Add(MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE);
297 pList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE);
298 pList->Add(MEDIA_PROPERTY_AUDIO_BIT_RATE);
307 _Mp3Decoder::IsPropertySupported(MediaPropertyType type) const
309 result r = E_SUCCESS;
311 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
312 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
313 SysTryCatch(NID_MEDIA, type == MEDIA_PROPERTY_AUDIO_SAMPLE_RATE ||
314 type == MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE ||
315 type == MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE ||
316 type == MEDIA_PROPERTY_AUDIO_BIT_RATE,
317 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
318 "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
\r