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 <FBaseInteger.h>
22 #include <FBaseColHashMap.h>
23 #include <FMediaTypes.h>
24 #include <FMediaAudioTypes.h>
25 #include <FBaseSysLog.h>
26 #include "FMedia_Ffmpeg.h"
27 #include "FMedia_FfmpegUtil.h"
28 #include "FMedia_IAudioDecoder.h"
29 #include "FMedia_G711Decoder.h"
32 using namespace Tizen::Base;
33 using namespace Tizen::Io;
34 using namespace Tizen::Base::Collection;
36 namespace Tizen { namespace Media
40 _AlawDecoder_CreateInstance(void)
42 return new (std::nothrow) _G711Decoder(G711_ALAW);
46 _UlawDecoder_CreateInstance(void)
48 return new (std::nothrow) _G711Decoder(G711_MULAW);
51 _G711Decoder::_G711Decoder(G711Type type)
52 : __pCodecCtx(null, ffmpegDeleter)
58 _G711Decoder::~_G711Decoder(void)
63 _G711Decoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
67 Integer* pValue = null;
70 std::unique_ptr<AVCodecContext, _FfmpegDeleter> pCodecCtx(null, ffmpegDeleter);
71 AVCodec* pCodec = null;
73 SysAssertf(__pCodecCtx.get() == null, " Already Constructed.");
74 SysTryReturnResult(NID_MEDIA, pOption != null, E_INVALID_ARG, "pOtion is null");
75 SysTryReturnResult(NID_MEDIA, __type >= G711_ALAW && __type <= G711_MULAW, E_INVALID_ARG, "__type is invalid:%d", __type);
77 avcodec_register_all();
79 AVCodecID codecId = (__type == G711_ALAW) ? CODEC_ID_PCM_ALAW : CODEC_ID_PCM_MULAW;
80 pCodec = avcodec_find_decoder(codecId);
81 SysTryReturnResult(NID_MEDIA, pCodec != null, E_UNSUPPORTED_FORMAT, "Find Decoder Failed:%d", codecId);
83 pCodecCtx.reset(avcodec_alloc_context3(pCodec));
84 SysTryReturnResult(NID_MEDIA, pCodecCtx.get() != null, E_OUT_OF_MEMORY, "Context Allcoation Failed");
86 // The initialization values are given in the Hashmap
87 std::unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
88 if (pMapEnum.get() != null )
90 while (pMapEnum->MoveNext() == E_SUCCESS)
92 pKey = static_cast<Integer*>(pMapEnum->GetKey());
93 pValue = static_cast<Integer*>(pMapEnum->GetValue());
94 if (pKey == null || pValue == null)
98 value = pValue->ToInt();
101 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
102 SysTryReturnResult(NID_MEDIA, value == 1 || value == 2, E_OUT_OF_RANGE, "Invalid channel type: %d", value);
103 pCodecCtx->channels = value;
106 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
107 SysTryReturnResult(NID_MEDIA, value > 0, E_OUT_OF_RANGE, "Invalid sample rate: %d", value);
108 pCodecCtx->sample_rate = value;
111 case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
112 SysTryReturnResult(NID_MEDIA, value > 0, E_OUT_OF_RANGE, "Invalid sample type: %d", value);
113 pCodecCtx->sample_fmt = _FfmpegUtil::ToAvSampleFormat((AudioSampleType)value);
122 SysTryReturnResult(NID_MEDIA, pCodecCtx->channels != 0, E_INVALID_ARG, "Channel is not set");
123 SysTryReturnResult(NID_MEDIA, pCodecCtx->sample_rate != 0, E_INVALID_ARG, "Sample rate is not set");
124 SysTryReturnResult(NID_MEDIA, pCodecCtx->sample_fmt != AV_SAMPLE_FMT_NONE, E_INVALID_ARG, "Sample type is not set");
126 res = avcodec_open2(pCodecCtx.get(), pCodec, null);
127 SysTryReturnResult(NID_MEDIA, res >= 0, E_UNSUPPORTED_FORMAT, "codec open failed:%d %d", res, __type);
129 // AVCodecContext parameters
130 if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
132 pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
135 pCodecCtx->debug_mv = 0; //set by user
136 pCodecCtx->debug = 0; //set by user
137 pCodecCtx->workaround_bugs = 1; //set by user
138 pCodecCtx->lowres = 0; //set by user
140 __pCodecCtx.reset(pCodecCtx.release());
147 _G711Decoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
148 byte* pDstBuf, int dstBufSize, int& dstBufUsed)
151 AVPacket inputPacket;
153 unique_ptr<AVFrame, _FfmpegDeleter> pOutFrame(avcodec_alloc_frame(), ffmpegDeleter);
156 SysAssertf(__pCodecCtx.get() != null, "Not Constructed.");
157 SysTryReturnResult(NID_MEDIA, pSrcBuf != null && pDstBuf != null && srcBufSize > 0 && dstBufSize > 0, E_INVALID_ARG,
158 "Invalid argument: pSrcBuf(0x%x), srcBufSize(%d), pDstBuf(0x%x), dstBufSize(%d)",
159 pSrcBuf, srcBufSize, pDstBuf, dstBufSize);
160 SysTryReturnResult(NID_MEDIA, pOutFrame.get() != null, E_OUT_OF_MEMORY, "alloc frame failed");
162 av_init_packet(&inputPacket);
164 inputPacket.size = srcBufSize;
165 inputPacket.data = (uint8_t*)pSrcBuf;
167 res = avcodec_decode_audio4(__pCodecCtx.get(), pOutFrame.get(), &gotFrame, &inputPacket);
168 SysTryReturnResult(NID_MEDIA, res > 0, E_UNSUPPORTED_FORMAT, "decode audio failed:%d", res);
172 outBufSize = av_samples_get_buffer_size(NULL, __pCodecCtx->channels, pOutFrame->nb_samples, __pCodecCtx->sample_fmt, 1);
174 SysTryReturnResult(NID_MEDIA, dstBufSize >= outBufSize, E_OUT_OF_MEMORY, "pDstBuf(%d) is smaller than decoded data(%d)", dstBufSize, outBufSize);
176 dstBufUsed = outBufSize; // The decoded audio data size
177 memcpy(pDstBuf, pOutFrame->data[0], outBufSize);
184 srcBufUsed = res; // input bytes used
190 _G711Decoder::Probe(const byte* pSrcBuf, const int srcBufSize,
191 AudioSampleType& sampleType, AudioChannelType& channelType, int& sampleRate)
193 result r = E_SUCCESS;
196 unique_ptr<byte[]> pOutBuf(new (std::nothrow) byte[MIN_OUT_BUFFER_SIZE]);
198 r = Decode(pSrcBuf, srcBufSize, srcBufUsed, pOutBuf.get(), MIN_OUT_BUFFER_SIZE, dstBufUsed);
200 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Decode failed", GetErrorMessage(r));
202 channelType = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
203 sampleType = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
204 sampleRate = __pCodecCtx->sample_rate;
206 SetLastResult(E_SUCCESS);
211 _G711Decoder::Reset(void)
213 result r = E_SUCCESS;
215 SysAssertf(__pCodecCtx.get() != null, "Not Constructed.");
217 avcodec_flush_buffers(__pCodecCtx.get());
219 SetLastResult(E_SUCCESS);
224 _G711Decoder::GetValue(MediaPropertyType type, int& value) const
226 result r = E_SUCCESS;
228 SysAssertf(__pCodecCtx.get() != null, "Not Constructed.");
229 SysTryReturnResult(NID_MEDIA, type > 0, E_INVALID_ARG, "Invalid type: %d", type);
233 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
234 value = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
237 case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
238 value = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
241 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
242 value = __pCodecCtx->sample_rate;
254 _G711Decoder::GetValue(MediaPropertyType type, float& value) const
256 SysAssertf(__pCodecCtx.get() != null, "Not Constructed.");
257 SysTryReturnResult(NID_MEDIA, type > 0, E_INVALID_ARG, "Invalid type: %d", type);
259 return E_OBJ_NOT_FOUND;
262 Tizen::Base::Collection::IListT<MediaPropertyType>*
263 _G711Decoder::GetSupportedPropertyListN(void) const
265 ArrayListT<MediaPropertyType>* pList = new (std::nothrow) ArrayListT<MediaPropertyType>;
267 SysTryReturn(NID_MEDIA, pList != null, null, E_OUT_OF_MEMORY, "[%s] new ArrayListT Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
269 pList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_RATE);
270 pList->Add(MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE);
271 pList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE);
272 SetLastResult(E_SUCCESS);
277 _G711Decoder::IsPropertySupported(MediaPropertyType type) const
279 SysTryReturn(NID_MEDIA, type == MEDIA_PROPERTY_AUDIO_SAMPLE_RATE ||
280 type == MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE ||
281 type == MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE, false,
283 "[%s] The property is not available:%d",GetErrorMessage(E_OBJ_NOT_FOUND), type);
284 SetLastResult(E_SUCCESS);