571e5bdcdc5a928e6069a564fb7d4f54117fe02a
[platform/framework/native/media.git] / src / FMedia_G711Decoder.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17
18 #include <stdio.h>
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"
30
31 using namespace std;
32 using namespace Tizen::Base;
33 using namespace Tizen::Io;
34 using namespace Tizen::Base::Collection;
35
36 namespace Tizen { namespace Media
37 {
38
39 _IAudioDecoder*
40 _AlawDecoder_CreateInstance(void)
41 {
42         return new (std::nothrow) _G711Decoder(G711_ALAW);
43 }
44
45 _IAudioDecoder*
46 _UlawDecoder_CreateInstance(void)
47 {
48         return new (std::nothrow) _G711Decoder(G711_MULAW);
49 }
50
51 _G711Decoder::_G711Decoder(G711Type type)
52         : __pCodecCtx(null, ffmpegDeleter)
53 {
54         __pCodec = null;
55         __type = type;
56 }
57
58 _G711Decoder::~_G711Decoder(void)
59 {
60 }
61
62 result
63 _G711Decoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
64 {
65         int res = 0;
66         Integer* pKey = null;
67         Integer* pValue = null;
68         int key = -1;
69         int value = -1;
70         std::unique_ptr<AVCodecContext, _FfmpegDeleter> pCodecCtx(null, ffmpegDeleter);
71         AVCodec* pCodec = null;
72
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);
76
77         avcodec_register_all();
78
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);
82
83         pCodecCtx.reset(avcodec_alloc_context3(pCodec));
84         SysTryReturnResult(NID_MEDIA, pCodecCtx.get() != null, E_OUT_OF_MEMORY, "Context Allcoation Failed");
85
86         // The initialization values are given in the Hashmap
87         std::unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
88         if (pMapEnum.get() != null )
89         {
90                 while (pMapEnum->MoveNext() == E_SUCCESS)
91                 {
92                         pKey = static_cast<Integer*>(pMapEnum->GetKey());
93                         pValue = static_cast<Integer*>(pMapEnum->GetValue());
94                         if (pKey == null || pValue == null)
95                                 continue;
96
97                         key = pKey->ToInt();
98                         value = pValue->ToInt();
99                         switch (key)
100                         {
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;
104                                 break;
105
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;
109                                 break;
110
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);
114                                 break;
115
116                         default:
117                                 break;
118                         }
119                 } // while
120         }
121
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");
125
126         res = avcodec_open2(pCodecCtx.get(), pCodec, null);
127         SysTryReturnResult(NID_MEDIA, res >= 0, E_UNSUPPORTED_FORMAT, "codec open failed:%d %d", res, __type);
128
129         // AVCodecContext parameters
130         if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
131         {
132                 pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
133         }
134
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
139
140         __pCodecCtx.reset(pCodecCtx.release());
141         __pCodec = pCodec;
142
143         return E_SUCCESS;
144 }
145
146 result
147 _G711Decoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
148                                         byte* pDstBuf, int dstBufSize, int& dstBufUsed)
149 {
150         int res = 0;
151         AVPacket inputPacket;
152         int outBufSize = 0;
153         unique_ptr<AVFrame, _FfmpegDeleter> pOutFrame(avcodec_alloc_frame(), ffmpegDeleter);
154         int gotFrame = 0;
155
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");
161
162         av_init_packet(&inputPacket);
163
164         inputPacket.size = srcBufSize;
165         inputPacket.data = (uint8_t*)pSrcBuf;
166
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);
169
170         if (gotFrame)
171         {
172                 outBufSize = av_samples_get_buffer_size(NULL, __pCodecCtx->channels, pOutFrame->nb_samples, __pCodecCtx->sample_fmt, 1);
173
174                 SysTryReturnResult(NID_MEDIA, dstBufSize >= outBufSize, E_OUT_OF_MEMORY, "pDstBuf(%d) is smaller than decoded data(%d)", dstBufSize, outBufSize);
175
176                 dstBufUsed = outBufSize; // The decoded audio data size
177                 memcpy(pDstBuf, pOutFrame->data[0], outBufSize);
178         }
179         else
180         {
181                 dstBufUsed = 0;
182         }
183
184         srcBufUsed = res; // input bytes used
185
186         return E_SUCCESS;
187 }
188
189 result
190 _G711Decoder::Probe(const byte* pSrcBuf, const int srcBufSize,
191                                    AudioSampleType& sampleType, AudioChannelType& channelType, int& sampleRate)
192 {
193         result r = E_SUCCESS;
194         int dstBufUsed = 0;
195         int srcBufUsed = 0;
196         unique_ptr<byte[]> pOutBuf(new (std::nothrow) byte[MIN_OUT_BUFFER_SIZE]);
197
198         r = Decode(pSrcBuf, srcBufSize, srcBufUsed, pOutBuf.get(), MIN_OUT_BUFFER_SIZE, dstBufUsed);
199
200         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Decode failed", GetErrorMessage(r));
201
202         channelType = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
203         sampleType = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
204         sampleRate = __pCodecCtx->sample_rate;
205
206         SetLastResult(E_SUCCESS);
207         return E_SUCCESS;
208 }
209
210 result
211 _G711Decoder::Reset(void)
212 {
213         result r = E_SUCCESS;
214
215         SysAssertf(__pCodecCtx.get() != null, "Not Constructed.");
216
217         avcodec_flush_buffers(__pCodecCtx.get());
218
219         SetLastResult(E_SUCCESS);
220         return r;
221 }
222
223 result
224 _G711Decoder::GetValue(MediaPropertyType type, int& value) const
225 {
226         result r = E_SUCCESS;
227
228         SysAssertf(__pCodecCtx.get() != null, "Not Constructed.");
229         SysTryReturnResult(NID_MEDIA, type > 0, E_INVALID_ARG, "Invalid type: %d", type);
230
231         switch (type)
232         {
233         case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
234                 value = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
235                 break;
236
237         case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
238                 value = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
239                 break;
240
241         case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
242                 value = __pCodecCtx->sample_rate;
243                 break;
244
245         default:
246                 r = E_OBJ_NOT_FOUND;
247                 break;
248         }
249         SetLastResult(r);
250         return r;
251 }
252
253 result
254 _G711Decoder::GetValue(MediaPropertyType type, float& value) const
255 {
256         SysAssertf(__pCodecCtx.get() != null, "Not Constructed.");
257         SysTryReturnResult(NID_MEDIA, type > 0, E_INVALID_ARG, "Invalid type: %d", type);
258
259         return E_OBJ_NOT_FOUND;
260 }
261
262 Tizen::Base::Collection::IListT<MediaPropertyType>*
263 _G711Decoder::GetSupportedPropertyListN(void) const
264 {
265         ArrayListT<MediaPropertyType>* pList = new (std::nothrow) ArrayListT<MediaPropertyType>;
266
267         SysTryReturn(NID_MEDIA, pList != null, null, E_OUT_OF_MEMORY, "[%s] new ArrayListT Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
268
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);
273         return pList;
274 }
275
276 bool
277 _G711Decoder::IsPropertySupported(MediaPropertyType type) const
278 {
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,
282                            E_OBJ_NOT_FOUND,
283                           "[%s] The property is not available:%d",GetErrorMessage(E_OBJ_NOT_FOUND), type);
284         SetLastResult(E_SUCCESS);
285         return true;
286 }
287
288 } } // Tizen::Media