Tizen 2.0 Release
[framework/osp/media.git] / src / FMedia_AlawDecoder.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_AlawDecoder.h"
30
31 using namespace Tizen::Base;
32 using namespace Tizen::Io;
33 using namespace Tizen::Base::Collection;
34
35 namespace Tizen { namespace Media
36 {
37
38 _IAudioDecoder*
39 _AlawDecoder_CreateInstance(void)
40 {
41         return new (std::nothrow) _AlawDecoder();
42 }
43
44 _AlawDecoder::_AlawDecoder(void)
45 {
46         __pCodecCtx = null;
47         __pCodec = null;
48         __decodeCalled = false;
49         __pOutBuf = null;
50         __decoderConfigured = false;
51 }
52
53 _AlawDecoder::~_AlawDecoder(void)
54 {
55         if (__pCodecCtx != null)
56         {
57                 avcodec_close(__pCodecCtx);
58                 av_free(__pCodecCtx);
59         }
60         if (__pOutBuf != null)
61         {
62                 delete[] __pOutBuf;
63         }
64 }
65
66 result
67 _AlawDecoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
68 {
69         result r = E_SUCCESS;
70         int res = 0;
71         Integer* pKey = null;
72         Integer* pValue = null;
73         int key = -1;
74         int value = -1;
75
76         SysAssertf((__pCodecCtx == null && __pCodec == null), " Already Constructed .");
77         SysTryReturnResult(NID_MEDIA, pOption != null, E_INVALID_ARG, "pOtion is null");
78
79         avcodec_register_all();
80
81         __pCodecCtx = avcodec_alloc_context();
82         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
83                             "[%s] AVCODEC Context Allcoation Failed",GetErrorMessage(E_SYSTEM));
84         __pCodec = avcodec_find_decoder(CODEC_ID_PCM_ALAW);
85         SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
86                            "[%s] AVCODEC Find Decoder Failed for CODEC_ID_PCM_ALAW",GetErrorMessage(E_SYSTEM));
87
88         if (pOption != null)
89         {
90                 // The initialization values are given in the Hashmap
91                 std::unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
92                 if (pMapEnum.get() != null)
93                 {
94                         while (pMapEnum.get()->MoveNext() == E_SUCCESS)
95                         {
96                                 pKey = static_cast<Integer*>(pMapEnum.get()->GetKey());
97                                 pValue = static_cast<Integer*>(pMapEnum.get()->GetValue());
98                                 if (pKey && pValue)
99                                 {
100                                         key = pKey->ToInt();
101                                         value = pValue->ToInt();
102                                         switch (key)
103                                         {
104                                         case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
105                                                 SysTryCatch(NID_MEDIA, (value == 0 || value == 1 || value == 2), r = E_OUT_OF_RANGE,
106                                                                    E_OUT_OF_RANGE, "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
107                                                 __pCodecCtx->channels = value;
108                                                 __decoderConfigured = true;
109                                                 break;
110
111                                         case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
112                                                 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
113                                                                    "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
114                                                 __pCodecCtx->sample_rate = value;
115                                                 break;
116
117                                         case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
118                                                 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
119                                                                    "[%s] Invalid argument is used. The value is out of range",GetErrorMessage(E_OUT_OF_RANGE));
120                                                 __pCodecCtx->sample_fmt = _FfmpegUtil::ToAvSampleFormat((AudioSampleType)value);
121                                                 break;
122
123                                         default:
124                                                 break;
125                                         }
126                                 }
127                         } // while
128
129                 }
130         }
131
132         SysTryReturnResult(NID_MEDIA, __pCodecCtx->channels != 0, E_INVALID_ARG, "Channel is not set");
133         SysTryReturnResult(NID_MEDIA, __pCodecCtx->sample_rate != 0, E_INVALID_ARG, "Sample rate is not set");
134         SysTryReturnResult(NID_MEDIA, __pCodecCtx->sample_fmt != AV_SAMPLE_FMT_NONE, E_INVALID_ARG, "Sample type is not set");
135
136         res = avcodec_open(__pCodecCtx, __pCodec);
137         SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
138                            "[%s] AVCODEC Codec Open Failed for CODEC_ID_PCM_ALAW",GetErrorMessage(E_SYSTEM));
139
140         // AVCodecContext parameters
141         if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
142         {
143                 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
144         }
145
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->lowres = 0; //set by user
150
151         __pOutBuf = new (std::nothrow) byte[MIN_OUT_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));
154
155         return r;
156
157 CATCH:
158         if (__pCodecCtx != null)
159         {
160                 avcodec_close(__pCodecCtx);
161                 av_free(__pCodecCtx);
162                 __pCodecCtx = null;
163                 __pCodec = null;
164         }
165         if (__pOutBuf != null)
166         {
167                 delete[] __pOutBuf;
168                 __pOutBuf = null;
169         }
170         return r;
171 }
172
173 result
174 _AlawDecoder::Decode(const byte* pSrcBuf, int srcBufSize, int& srcBufUsed,
175                                         byte* pDstBuf, int dstBufSize, int& dstBufUsed)
176 {
177         result r = E_SUCCESS;
178         int res = 0;
179         AVPacket inputPacket;
180         int outBufSize = 0;
181         byte* pOutBuf = null;
182         int offSet = 0;
183
184
185         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
186                            "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
187         SysTryCatch(NID_MEDIA, pSrcBuf != null && pDstBuf != null && srcBufSize > 0 && dstBufSize > 0,
188                            r = E_INVALID_ARG, E_INVALID_ARG,
189                            "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
190
191         // This blocks reads the input data format , i.e channel count and format type is read.
192         // No error checkin id done here as we are trying to get the channel count if user wont specify
193 #if 0
194         if (__decoderConfigured == false)
195         {
196
197                 _WavFormatInfo wavFormatInfo;
198                 _RiffFileHeader riffHdr;
199                 _RiffChunkHeader chunkHdr;
200
201                 if ( srcBufSize > _MIN_WAVE_HEADER_SIZE )
202                 {
203                         memcpy(&riffHdr, pSrcBuf, sizeof(riffHdr)); // file header of 12 bytes
204                         offSet += sizeof(riffHdr);
205                         memcpy(&chunkHdr, pSrcBuf + offSet, sizeof(chunkHdr)); // format sub chunk  header of 8 bytes
206                         offSet += sizeof(chunkHdr);
207                         memcpy(&wavFormatInfo, pSrcBuf + offSet, sizeof(wavFormatInfo)); // format sub chunk consists of wave info 16 bytes
208                         offSet += sizeof(wavFormatInfo);
209                         // assign to codec context if it is mono or stereo
210                         if ( riffHdr.chunkId == _RIFF_CHUNK_ID && riffHdr.format== _RIFF_FORMAT_WAVE )
211                         {
212                                 __pCodecCtx->channels = wavFormatInfo.channels;
213                                 __decoderConfigured = true;
214                                 // Data starts in next sub chunk
215                                 memcpy(&chunkHdr, pSrcBuf + offSet, sizeof(chunkHdr)); // data sub chunk  header of 8 bytes
216                                 offSet += sizeof(chunkHdr); // offset is now at data start
217                         }
218                         else
219                         {
220                                 offSet = 0; // Header info is not available
221                         }
222
223                 }
224
225         }
226 #endif
227
228         av_init_packet(&inputPacket);
229
230         inputPacket.size = srcBufSize -offSet;
231         inputPacket.data = (uint8_t*)pSrcBuf + offSet;
232
233         if (dstBufSize >= MIN_OUT_BUFFER_SIZE)
234         {
235                 pOutBuf = pDstBuf;
236                 outBufSize = dstBufSize;
237         }
238         else
239         {
240                 pOutBuf = __pOutBuf;
241                 outBufSize = MIN_OUT_BUFFER_SIZE;
242         }
243
244         SysTryCatch(NID_MEDIA, __decoderConfigured == true, r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
245                            "[%s] The input data format is not supported ",GetErrorMessage(E_UNSUPPORTED_FORMAT));
246         res = avcodec_decode_audio3(__pCodecCtx, (int16_t*)pOutBuf, &outBufSize, &inputPacket);
247         SysTryCatch(NID_MEDIA, (res > 0 && outBufSize > 0), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
248                            "[%s] The input data format is not supported ",GetErrorMessage(E_UNSUPPORTED_FORMAT));
249
250         SysTryCatch(NID_MEDIA, dstBufSize >= outBufSize, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
251                            "[%s] Memory Allocation  Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
252
253         dstBufUsed = outBufSize; // the decoded audio data size
254         srcBufUsed = res + offSet; // // input bytes used + offset header that is skipped
255         if (pOutBuf != pDstBuf)
256         {
257                 memcpy(pDstBuf, pOutBuf, outBufSize);
258         }
259         __decodeCalled = true;
260         return r;
261
262 CATCH:
263         return r;
264 }
265
266 result
267 _AlawDecoder::Probe(const byte* pSrcBuf, const int srcBufSize,
268                                    AudioSampleType& sampleType, AudioChannelType& channelType, int& sampleRate)
269 {
270         result r = E_SUCCESS;
271         int dstBufUsed = 0;
272         int srcBufUsed = 0;
273
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));
276         SysTryCatch(NID_MEDIA, pSrcBuf != null && srcBufSize > 0, r = E_INVALID_ARG, E_INVALID_ARG,
277                            "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
278
279         r = Decode(pSrcBuf, srcBufSize, srcBufUsed, __pOutBuf, MIN_OUT_BUFFER_SIZE, dstBufUsed);
280
281         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Decode failed", GetErrorMessage(r));
282
283         channelType = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
284         sampleType = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
285         sampleRate = __pCodecCtx->sample_rate;
286
287         SetLastResult(E_SUCCESS);
288         return r;
289
290 CATCH:
291         return r;
292 }
293
294 result
295 _AlawDecoder::Reset(void)
296 {
297         result r = E_SUCCESS;
298
299         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
300                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
301
302         avcodec_flush_buffers(__pCodecCtx);
303
304         __decodeCalled = false;
305         __decoderConfigured = false;
306
307         SetLastResult(E_SUCCESS);
308         return r;
309
310 CATCH:
311         return r;
312 }
313
314 result
315 _AlawDecoder::GetValue(MediaPropertyType type, int& value) const
316 {
317         result r = E_SUCCESS;
318
319         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
320                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
321         SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
322                            "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
323         SysTryCatch(NID_MEDIA, __decodeCalled, r = E_INVALID_STATE, E_INVALID_STATE,
324                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
325
326         switch (type)
327         {
328         case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
329                 value = _FfmpegUtil::ToAudioChannelType(__pCodecCtx->channels);
330         break;
331
332         case MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE:
333                 value = _FfmpegUtil::ToAudioSampleType(__pCodecCtx->sample_fmt);
334         break;
335
336         case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
337                 value = __pCodecCtx->sample_rate;
338         break;
339
340         default:
341                 r = E_OBJ_NOT_FOUND;
342         break;
343         }
344         SetLastResult(r);
345         return r;
346
347 CATCH:
348         return r;
349 }
350
351 result
352 _AlawDecoder::GetValue(MediaPropertyType type, float& value) const
353 {
354         result r = E_SUCCESS;
355         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
356                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
357         SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
358                            "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
359         SysTryCatch(NID_MEDIA, __decodeCalled, r = E_INVALID_STATE, E_INVALID_STATE,
360                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
361
362         return E_OBJ_NOT_FOUND;
363
364 CATCH:
365         return r;
366 }
367
368 Tizen::Base::Collection::IListT<MediaPropertyType>*
369 _AlawDecoder::GetSupportedPropertyListN(void) const
370 {
371         result r = E_SUCCESS;
372         ArrayListT<MediaPropertyType>* pList = new (std::nothrow) ArrayListT<MediaPropertyType>;
373
374         SysTryCatch(NID_MEDIA, pList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
375                            "[%s] Memory Allocation  Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
376         pList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_RATE);
377         pList->Add(MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE);
378         pList->Add(MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE);
379         SetLastResult(r);
380         return pList;
381
382 CATCH:
383         return null;
384 }
385
386 bool
387 _AlawDecoder::IsPropertySupported(MediaPropertyType type) const
388 {
389         result r = E_SUCCESS;
390
391         SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_INVALID_STATE, E_INVALID_STATE,
392                             "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
393         SysTryCatch(NID_MEDIA, type == MEDIA_PROPERTY_AUDIO_SAMPLE_RATE ||
394                            type == MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE ||
395                            type == MEDIA_PROPERTY_AUDIO_SAMPLE_TYPE,
396                            r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
397                           "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
398         SetLastResult(r);
399         return true;
400
401 CATCH:
402         return false;
403 }
404
405 } } // Tizen::Media