Tizen 2.0 Release
[framework/osp/media.git] / src / FMedia_AudioOutImpl.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 <FMediaCapability.h>
19 #include <FBaseSysLog.h>
20 #include "FMedia_AudioOutEvent.h"
21 #include "FMedia_AudioOutImpl.h"
22 #include "FMedia_AudioOutEventArg.h"
23 #include "FMedia_AudioManagerConvert.h"
24
25
26 #define attribute_deprecated
27
28 #ifdef __cplusplus
29 #define __STDC_CONSTANT_MACROS
30 #ifdef _STDINT_H
31 #undef _STDINT_H
32 #endif
33 #include <stdint.h>
34 #endif
35
36 extern "C"
37 {
38 #include <stdlib.h>
39 #include <libswscale/swscale.h>
40 }
41
42 using namespace Tizen::Base;
43 using namespace Tizen::Base::Runtime;
44 using namespace Tizen::Base::Collection;
45
46 namespace Tizen { namespace Media
47 {
48
49 int _AudioOutImpl::instanceCount = 0;
50 int _AudioOutImpl::maxInstanceCount = 0;
51 AudioChannelType _AudioOutImpl::audioOutOptimalChannelType = AUDIO_CHANNEL_TYPE_STEREO;
52 AudioSampleType _AudioOutImpl::audioOutOptimalSampleType = AUDIO_TYPE_PCM_S16_LE;
53 int _AudioOutImpl::audioOutOptimalSampleRate = 44100;
54 int _AudioOutImpl::audioOutMinimumBufferSize = 2048;
55 int _AudioOutImpl::audioOutMaximumBufferSize = 164112;
56
57 std::unique_ptr<Tizen::Base::Runtime::Mutex> _AudioOutImpl::__pInstanceMutex;
58 bool _AudioOutImpl::__isInstanceMutexInitialized = false;
59
60 _AudioOutImpl::_AudioOutImpl(void)
61         : __pAudioOut(null)
62         , __pAudioOutEventListener(null)
63         , __audioOutState(AUDIOOUT_STATE_ERROR)
64         , __volume(-1)
65         , __volume256(-1)
66         , __presentSampleType(AUDIO_TYPE_NONE)
67         , __presentSampleRate(0)
68         , __audioOutHandle(null)
69         , __audioOutOptimalBufferSize(0)
70         , __stop(false)
71         , __interruptFlag(false)
72 {
73 }
74
75
76 _AudioOutImpl::~_AudioOutImpl(void)
77 {
78         if (__audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED)
79         {
80                 if (__audioOutState == AUDIOOUT_STATE_PLAYING )
81                 {
82                         this->Stop();
83                 }
84                 this->Reset();
85                 this->UnPrepare();
86         }
87         __pAudioOut = null;
88         if (__pAudioOutEvent.get() && __pAudioOutEventListener)
89         {
90                 __pAudioOutEvent->RemoveListener(*__pAudioOutEventListener);
91         }
92
93         if ((__audioOutState == AUDIOOUT_STATE_INITIALIZED ) || __audioOutState == AUDIOOUT_STATE_UNPREPARED )
94         {
95                 __pInstanceMutex->Acquire();
96                 instanceCount--;
97                 __pInstanceMutex->Release();
98         }
99 }
100
101 void
102 _AudioOutImpl::InitInstanceMutex(void)
103 {
104         result r = E_SUCCESS;
105         __pInstanceMutex.reset(new (std::nothrow) Tizen::Base::Runtime::Mutex);
106         SysTryReturn(NID_MEDIA, __pInstanceMutex.get() != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] no memory to create instance Mutex");
107         r = __pInstanceMutex->Create("FMEDIA_AUDIOOUT_N");
108         SysTryReturn(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Mutex::Create failed.");
109         __isInstanceMutexInitialized  = true;
110 }
111
112 _AudioOutImpl*
113 _AudioOutImpl::GetInstance(AudioOut* pAudioOut)
114 {
115         if (pAudioOut != null)
116         {
117                 return pAudioOut->__pAudioOutImpl;
118         }
119
120         return null;
121 }
122
123 const _AudioOutImpl*
124 _AudioOutImpl::GetInstance(const AudioOut* pAudioOut)
125 {
126         if (pAudioOut != null)
127         {
128                 return pAudioOut->__pAudioOutImpl;
129         }
130
131         return null;
132 }
133
134 result
135 _AudioOutImpl::Construct(const Tizen::Media::AudioOut* pAudioOut, Tizen::Media::IAudioOutEventListener& listener)
136 {
137         result r = E_SUCCESS;
138         __pAudioOut = const_cast <AudioOut*>(pAudioOut);
139         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
140         if (!__isInstanceMutexInitialized)
141         {
142                 pthread_once(&onceBlock, InitInstanceMutex);
143         }
144         SysTryCatch(NID_MEDIA, __isInstanceMutexInitialized == true, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] memory allocation for Instance Mutex failed");
145
146         if (!maxInstanceCount)
147         {
148                 r = MediaCapability::GetValue(AUDIOOUT_COUNT_MAX, maxInstanceCount);
149                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
150                 SysTryCatch(NID_MEDIA, maxInstanceCount > 0, , r, "[%s] Propagating.", GetErrorMessage(r));
151         }
152
153         SysTryCatch(NID_MEDIA, instanceCount < maxInstanceCount, r = E_RESOURCE_UNAVAILABLE, E_RESOURCE_UNAVAILABLE, "[E_RESOURCE_UNAVAILABLE] The number of instances exceeds the available number of instances. The current number of instance is %d", instanceCount);
154
155         //Setting up the Events
156         __pAudioOutEvent.reset(new (std::nothrow) _AudioOutEvent);
157         SysTryReturnResult(NID_MEDIA, __pAudioOutEvent.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
158         r = __pAudioOutEvent->Construct(__pAudioOut);
159         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
160         r = __pAudioOutEvent->AddListener(listener);
161         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
162
163         //BufferQueue
164         r = __bufferQueue.Construct();
165         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
166         //Buffer Sync
167         __pBufferSync.reset( new (std::nothrow) Monitor);
168         SysTryCatch(NID_MEDIA, __pBufferSync.get() != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
169         r = __pBufferSync->Construct();
170         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
171
172         __volume = 50;
173         __volume256 = (__volume << 8) / 100;
174
175         __pInstanceMutex->Acquire();
176         instanceCount++;
177         __pInstanceMutex->Release();
178
179         __audioOutState = AUDIOOUT_STATE_INITIALIZED;
180         return E_SUCCESS;
181
182 CATCH:
183         __pAudioOut = null;
184         SetLastResult(r);
185         return r;
186 }
187
188 int
189 _AudioOutImpl::GetMaxBufferSize(void)
190 {
191         result r = E_SUCCESS;
192         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
193                 r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
194         return audioOutMaximumBufferSize;
195 CATCH:
196         SetLastResult(r);
197         return -1;
198 }
199
200 int
201 _AudioOutImpl::GetMinBufferSize(void)
202 {
203         result r = E_SUCCESS;
204         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
205                 r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
206         return audioOutMinimumBufferSize;
207 CATCH:
208         SetLastResult(r);
209         return -1;
210 }
211
212 AudioChannelType
213 _AudioOutImpl::GetOptimizedChannelType(void)
214 {
215         return audioOutOptimalChannelType;
216 }
217
218 int
219 _AudioOutImpl::GetOptimizedSampleRate(void)
220 {
221         result r = E_SUCCESS;
222         SetLastResult(r);
223         return audioOutOptimalSampleRate;
224 }
225
226 AudioSampleType
227 _AudioOutImpl::GetOptimizedSampleType(void)
228 {
229         return audioOutOptimalSampleType;
230 }
231
232 AudioOutState
233 _AudioOutImpl::GetState(void)
234 {
235         result r = E_SUCCESS;
236         SetLastResult(r);
237         SysLog(NID_MEDIA, "The current state of this instance is %d", __audioOutState);
238         return __audioOutState;
239 }
240
241 int
242 _AudioOutImpl::GetVolume(void) const
243 {
244         result r = E_SUCCESS;
245         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
246         r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
247         return __volume;
248 CATCH:
249         SetLastResult(r);
250         return -1;
251 }
252
253 result
254 _AudioOutImpl::SetVolume(int& volume)
255 {
256         result r = E_SUCCESS;
257         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
258                 r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
259         __volume = volume;
260         __volume256 = (__volume << 8) / 100;
261 CATCH:
262         return r;
263
264 }
265
266 result
267 _AudioOutImpl::Prepare(AudioSampleType audioSampleType, AudioChannelType audioChannelType, int audioSampleRate)
268 {
269         result r = E_SUCCESS;
270         int ret = 0;
271
272         SysTryReturnResult(NID_MEDIA, __audioOutState == AUDIOOUT_STATE_UNPREPARED || __audioOutState == AUDIOOUT_STATE_INITIALIZED,
273                 E_INVALID_STATE, "The state of this instance is in an invalid state.");
274         SysTryReturnResult(NID_MEDIA, audioSampleType >= AUDIO_TYPE_PCM_U8 && audioSampleType < AUDIO_TYPE_PCM_S16_BE, E_UNSUPPORTED_FORMAT,
275                 "Audio sample type is not valid.");
276         SysTryReturnResult(NID_MEDIA, audioChannelType == AUDIO_CHANNEL_TYPE_MONO || audioChannelType == AUDIO_CHANNEL_TYPE_STEREO, E_INVALID_ARG,
277                 "Invalid argument is used. Audio channel type is not valid");
278         SysTryReturnResult(NID_MEDIA, audioSampleRate >= 8000 && audioSampleRate <= 48000, E_INVALID_ARG,
279                 "Invalid argument is used. Audio sample rate is not valid.");
280
281         ret = audio_out_create(audioSampleRate, _AudioManagerConvert::ConvertChannelType(audioChannelType), _AudioManagerConvert::ConvertSampleType(audioSampleType), SOUND_TYPE_MEDIA, &__audioOutHandle);
282         r = MapExceptionToResult(ret);
283         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_create operation with error code : 0x%x", GetErrorMessage(r), ret);
284
285         ret = audio_out_set_interrupted_cb(__audioOutHandle, AudioIoInterrupted, this);
286         r = MapExceptionToResult(ret);
287         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
288                 "[%s] Failed to perform audio_out_set_interrupted_cb operation with error code : 0x%x", GetErrorMessage(r), ret);
289
290         ret = audio_out_get_buffer_size(__audioOutHandle, &__audioOutOptimalBufferSize);
291         if (ret == AUDIO_IO_ERROR_NONE)
292         {
293                 SysLog(NID_MEDIA, "The optimal buffer size is %d", __audioOutOptimalBufferSize);
294         }
295         else
296         {
297                 r = MapExceptionToResult(ret);
298                 SysLogException(NID_MEDIA, r, "[%s] Failed to perform audio_out_get_buffer_size operation with error code : %x", GetErrorMessage(r), ret);
299         }
300
301         __audioOutOptimalBufferSize = 1024;
302         __presentSampleType = audioSampleType;
303         __presentSampleRate = audioSampleRate;
304
305         __audioOutState = AUDIOOUT_STATE_PREPARED;
306         return r;
307 CATCH:
308         __audioOutHandle = null;
309         return r;
310 }
311
312 result
313 _AudioOutImpl::Prepare(AudioStreamType audioStreamType, AudioSampleType audioSampleType, AudioChannelType audioChannelType, int audioSampleRate)
314 {
315         result r = E_SUCCESS;
316         int ret = 0;
317
318         SysTryReturnResult(NID_MEDIA, __audioOutState == AUDIOOUT_STATE_UNPREPARED || __audioOutState == AUDIOOUT_STATE_INITIALIZED,
319                 E_INVALID_STATE, "The state of this instance is in an invalid state.");
320         SysTryReturnResult(NID_MEDIA, audioSampleType >= AUDIO_TYPE_PCM_U8 && audioSampleType < AUDIO_TYPE_PCM_S16_BE, E_UNSUPPORTED_FORMAT,
321                 "Audio sample type is not valid.");
322         SysTryReturnResult(NID_MEDIA, audioChannelType == AUDIO_CHANNEL_TYPE_MONO || audioChannelType == AUDIO_CHANNEL_TYPE_STEREO, E_INVALID_ARG,
323                 "Invalid argument is used. Audio channel type is not valid");
324         SysTryReturnResult(NID_MEDIA, audioSampleRate >= 8000 && audioSampleRate <= 48000, E_INVALID_ARG,
325                 "Invalid argument is used. Audio sample rate is not valid.");
326
327         ret = audio_out_create(audioSampleRate, _AudioManagerConvert::ConvertChannelType(audioChannelType), _AudioManagerConvert::ConvertSampleType(audioSampleType), _AudioManagerConvert::ConvertAudioStreamType2SoundType(audioStreamType), &__audioOutHandle);
328         r = MapExceptionToResult(ret);
329         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_create operation with error code : 0x%x", GetErrorMessage(r), ret);
330
331         ret = audio_out_prepare(__audioOutHandle);
332         r = MapExceptionToResult(ret);
333         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_prepare operation with error code : 0x%x", GetErrorMessage(r), ret);
334
335         ret = audio_out_set_interrupted_cb(__audioOutHandle, AudioIoInterrupted, this);
336         r = MapExceptionToResult(ret);
337         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_set_interrupted_cb operation with error code : 0x%x", GetErrorMessage(r), ret);
338
339         ret = audio_out_get_buffer_size(__audioOutHandle, &__audioOutOptimalBufferSize);
340         if (ret == AUDIO_IO_ERROR_NONE)
341         {
342                 SysLog(NID_MEDIA, "The optimal buffer size is %d", __audioOutOptimalBufferSize);
343         }
344         else
345         {
346                 r = MapExceptionToResult(ret);
347                 SysLogException(NID_MEDIA, r, "[%s] Failed to perform audio_out_get_buffer_size operation with error code : %x", GetErrorMessage(r), ret);
348         }
349
350         __audioOutOptimalBufferSize = 1024;
351         __presentSampleType = audioSampleType;
352         __presentSampleRate = audioSampleRate;
353
354         __audioOutState = AUDIOOUT_STATE_PREPARED;
355         return r;
356 CATCH:
357         __audioOutHandle = null;
358         return r;
359 }
360
361 result
362 _AudioOutImpl::Reset(void)
363 {
364         result r = E_SUCCESS;
365         SysTryReturnResult(NID_MEDIA, __audioOutState <AUDIOOUT_STATE_UNPREPARED && __audioOutState> AUDIOOUT_STATE_PREPARED, E_INVALID_STATE,
366                 "The state of this instance is in an invalid state. the current state is %d.", __audioOutState);
367         if (__audioOutState == AUDIOOUT_STATE_PLAYING )
368         {
369                 Stop();
370         }
371         __bufferQueue.RemoveAll();
372         __audioOutState = AUDIOOUT_STATE_PREPARED;
373         return r;
374 }
375
376 result
377 _AudioOutImpl::UnPrepare(void)
378 {
379         result r = E_SUCCESS;
380         int ret = 0;
381
382         SysTryReturnResult(NID_MEDIA, __audioOutState == AUDIOOUT_STATE_PREPARED || __audioOutState == AUDIOOUT_STATE_STOPPED, E_INVALID_STATE,
383                 "The state of this instance is in an invalid state. the current state is %d", __audioOutState);
384         __bufferQueue.RemoveAll();
385
386         ret = audio_out_unprepare(__audioOutHandle);
387         r = MapExceptionToResult(ret);
388         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_prepare operation with error code : %x", GetErrorMessage(r), ret);
389
390         SysTryCatch(NID_MEDIA, __audioOutHandle, r = E_SYSTEM, E_SYSTEM, "__audioout Handle is NULL");
391
392         ret = audio_out_unset_interrupted_cb(__audioOutHandle);
393         r = MapExceptionToResult(ret);
394         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_unset_interrupted_cb operation with error code : %x", GetErrorMessage(r), ret);
395
396         ret = audio_out_destroy(__audioOutHandle);
397         r = MapExceptionToResult(ret);
398         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_destroy operation with error code : %d", GetErrorMessage(r), ret);
399         __audioOutHandle = null;
400
401         __audioOutState = AUDIOOUT_STATE_UNPREPARED;
402         return r;
403 CATCH:
404         return r;
405 }
406
407 result
408 _AudioOutImpl::Start(void)
409 {
410         result r = E_SUCCESS;
411         int ret = 0;
412         SysTryReturnResult(NID_MEDIA, __audioOutState == AUDIOOUT_STATE_PREPARED || __audioOutState == AUDIOOUT_STATE_STOPPED, E_INVALID_STATE,
413                 "The state of this instance is in an invalid state.");
414
415         ret = audio_out_prepare(__audioOutHandle);
416         r = MapExceptionToResult(ret);
417         SysTryReturnResult(NID_MEDIA, r != E_DEVICE_BUSY, E_DEVICE_BUSY, "AudioOut cannot Start, higher priority task at work.");
418         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
419                 "[%s] Failed to perform audio_out_prepare operation with error code :  0x%x", GetErrorMessage(r), ret);
420
421         __stop = false;
422         __pWorkerThread.reset(new (std::nothrow) Thread);
423         SysTryReturnResult(NID_MEDIA, __pWorkerThread.get() != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
424         r = __pWorkerThread->Construct(*this);
425         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
426         r = __pWorkerThread->Start();
427         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
428         __audioOutState = AUDIOOUT_STATE_PLAYING;
429         return r;
430 CATCH:
431         SetLastResult(r);
432         return r;
433 }
434
435 result
436 _AudioOutImpl::Stop(void)
437 {
438         result r = E_SUCCESS;
439         SysTryReturnResult(NID_MEDIA, __audioOutState == AUDIOOUT_STATE_PLAYING, E_INVALID_STATE,
440                 "The state of this instance is in an invalid state. The current state is %d", __audioOutState);
441         if (__pWorkerThread.get())
442         {
443                 __stop = true;
444                 __pBufferSync->Notify();
445                 r = __pWorkerThread->Join();
446                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
447         }
448         else
449         {
450                 SysLog(NID_MEDIA, "Thread is null.");
451         }
452         __audioOutState = AUDIOOUT_STATE_STOPPED;
453         return r;
454 }
455
456 result
457 _AudioOutImpl::WriteBuffer(const Tizen::Base::ByteBuffer& userData)
458 {
459         result r = E_SUCCESS;
460         int size = userData.GetLimit();
461         SysTryReturnResult(NID_MEDIA, __audioOutState >= AUDIOOUT_STATE_PREPARED && __audioOutState < AUDIOOUT_STATE_UNPREPARED, E_INVALID_STATE,
462                 "The state of this instance is in an invalid state.");
463         SysTryReturnResult(NID_MEDIA, (size >= audioOutMinimumBufferSize), E_INVALID_ARG,
464                 "Invalid argument is used. The size of buffer is too small, the current size of buffer is %d. It should be between %d and %d",
465                         audioOutMinimumBufferSize, size, audioOutMaximumBufferSize);
466         SysTryReturnResult(NID_MEDIA, audioOutMaximumBufferSize >= size, E_OVERFLOW, "The size of buffer size is too big, the current size is %d. It should be between %d and %d", audioOutMinimumBufferSize, size, audioOutMaximumBufferSize);
467
468         __pBufferSync->Enter();
469         r = __bufferQueue.Enqueue(&const_cast <ByteBuffer&>(userData));
470         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
471         __pBufferSync->Notify();
472         __pBufferSync->Exit();
473         return r;
474 CATCH:
475         __pBufferSync->Exit();
476         return r;
477 }
478
479 Tizen::Base::Object*
480 _AudioOutImpl::Run(void)
481 {
482         ByteBuffer* pBuffer = null;
483         int buffer_size = 0;
484         unsigned char* pData = NULL;
485         result r = E_SUCCESS;
486         int ret = 0;
487         bool isSuccesful = true;
488         while (!__stop)
489         {
490                 if (isSuccesful)
491                 {
492                         __pBufferSync->Enter();
493                         if ( __bufferQueue.Peek(pBuffer) == E_UNDERFLOW)
494                         {
495                                 //wait
496                                 __pBufferSync->Wait();
497                                 if (__stop)
498                                 {
499                                         __pBufferSync->Exit();
500                                         return this;
501                                 }
502                                 __bufferQueue.Peek(pBuffer);
503                         }
504                         __pBufferSync->Exit();
505
506                         SysTryCatch(NID_MEDIA, pBuffer, r = E_INVALID_ARG, E_INVALID_ARG,
507                                 "[E_INVALID_ARG] Invalid argument is used. The buffer to write is null.");
508
509                         if ((__volume >= 0) && (__volume < 100))
510                         {
511                                 PreProcess(pBuffer);
512                         }
513                         isSuccesful = false;
514                 }
515
516                 buffer_size = pBuffer->GetLimit();
517                 pData = (unsigned char*) pBuffer->GetPointer();
518                 SysTryCatch(NID_MEDIA, pData, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument is used. The data to write is null");
519                 if (!__stop)
520                 {
521                         ret = audio_out_write(__audioOutHandle, (void*) pData, buffer_size);
522                         if (ret != buffer_size)
523                         {
524                                 SysLog(NID_MEDIA, "The size of actual written data is %d", ret);
525                         }
526                         else
527                         {
528                                 isSuccesful = true;
529                                 if (!__stop)
530                                 {
531                                         __pBufferSync->Enter();
532                                         __bufferQueue.Dequeue(pBuffer);
533                                         __pBufferSync->Exit();
534                                         pBuffer = NULL;
535                                         SendBufferEndReachedEvent();
536
537                                 }
538                         }
539                 }
540         }
541         return this;
542 CATCH:
543         return this;
544 }
545
546 void
547 _AudioOutImpl::AudioIoInterrupted(audio_io_interrupted_code_e code, void *pUserData)
548 {
549         SysTryReturn(NID_MEDIA, pUserData, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred. The value of pUserData is null.");
550         _AudioOutImpl *pAudioOutImpl = (_AudioOutImpl *)pUserData;
551
552         switch(code)
553         {
554         case AUDIO_IO_INTERRUPTED_COMPLETED:
555                 if (pAudioOutImpl->__audioOutState == AUDIOOUT_STATE_STOPPED)
556                 {
557                         if (!(pAudioOutImpl->__interruptFlag))
558                         {
559                                 pAudioOutImpl->SendReleased();
560                         }
561                         pAudioOutImpl->__interruptFlag = false;
562                 }
563                 break;
564         case AUDIO_IO_INTERRUPTED_BY_CALL:
565                 pAudioOutImpl->__interruptFlag = true;
566                 //Intentional Fall through
567         case AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG:
568                 //Intentional Fall through
569         case AUDIO_IO_INTERRUPTED_BY_MEDIA:
570                 //Intentional Fall through
571         case AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT:
572                 if (pAudioOutImpl->__audioOutState == AUDIOOUT_STATE_PLAYING)
573                 {
574                         pAudioOutImpl->SendAudioFocusChanged();
575                 }
576                 break;
577         case AUDIO_IO_INTERRUPTED_BY_ALARM:
578                 //Intentional Fall through
579         case AUDIO_IO_INTERRUPTED_BY_EMERGENCY:
580                 if (pAudioOutImpl->__audioOutState == AUDIOOUT_STATE_PLAYING)
581                 {
582                         pAudioOutImpl->SendInterrupted();
583                 }
584                 break;
585         default:
586                 SysLog(NID_MEDIA, "Interrupt code obtained is wrong - %d", code);
587                 break;
588         }
589 }
590
591 result
592 _AudioOutImpl::SendBufferEndReachedEvent(void)
593 {
594         result r = E_SUCCESS;
595         _AudioOutEventArg* pAudioOutEventArg = null;
596         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
597         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
598
599         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_DATA_END_REACHED);
600         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
601         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
602         return r;
603 CATCH:
604         delete pAudioOutEventArg;
605         return r;
606 }
607
608 result
609 _AudioOutImpl::SendInterrupted()
610 {
611         result r = E_SUCCESS;
612         _AudioOutEventArg* pAudioOutEventArg = null;
613         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
614         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
615         this->Stop();
616         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_INTERRUPTED);
617         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
618         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
619         return r;
620 CATCH:
621         delete pAudioOutEventArg;
622         return r;
623 }
624
625 result
626 _AudioOutImpl::SendAudioFocusChanged()
627 {
628         result r = E_SUCCESS;
629         _AudioOutEventArg* pAudioOutEventArg = null;
630         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
631         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
632         this->Stop();
633         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_AUDIO_FOCUS_CHANGED);
634         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
635         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
636         return r;
637 CATCH:
638         delete pAudioOutEventArg;
639         return r;
640 }
641
642 result
643 _AudioOutImpl::SendReleased()
644 {
645         result r = E_SUCCESS;
646         _AudioOutEventArg* pAudioOutEventArg = null;
647         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
648         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
649         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_RELEASED);
650         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
651         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
652         return r;
653 CATCH:
654         delete pAudioOutEventArg;
655         return r;
656 }
657
658 void
659 _AudioOutImpl::ScaleDownVolume(unsigned char* pDataBuffer, int bytes)
660 {
661         switch (__presentSampleType)
662         {
663         case AUDIO_TYPE_PCM_U8:
664         {
665                 unsigned char* pData = pDataBuffer;
666                 int noOfSamples = bytes;
667                 for (int i = 0; i < noOfSamples; i++)
668                 {
669                         int v = (((*pData - 128) * __volume256 + 128) >> 8) + 128;
670                         *pData++ = av_clip_uint8(v);
671                 }
672         }
673         break;
674
675         case AUDIO_TYPE_PCM_S16_LE:
676         {
677                 short* pData = (short*) pDataBuffer;
678                 int noOfSamples = bytes >> 1;
679                 for (int i = 0; i < noOfSamples; i++)
680                 {
681                         int v = ((*pData) * __volume256 + 128) >> 8;
682                         *pData++ = av_clip_int16(v);
683                 }
684         }
685         break;
686
687         default:
688                 break;
689         }
690 }
691
692 void
693 _AudioOutImpl::PreProcess(ByteBuffer* pBuffer)
694 {
695         unsigned char* pDataBuffer = null;
696         int bytes = 0;
697         if (pBuffer->GetLimit() > 0)
698         {
699                 pDataBuffer = (unsigned char*) pBuffer->GetPointer();
700                 if (!pDataBuffer)
701                 {
702                         return;
703                 }
704                 bytes = pBuffer->GetLimit();
705         }
706         else
707         {
708                 return;
709         }
710         if ((__volume256 < 256) && (__volume256 >= 0))
711         {
712                 ScaleDownVolume(pDataBuffer, bytes);
713         }
714 }
715
716 result
717 _AudioOutImpl::MapExceptionToResult(int reason)
718 {
719         //All the fall through are intentional
720         switch (reason)
721         {
722         //Successful
723         case AUDIO_IO_ERROR_NONE:
724                 return E_SUCCESS;
725                 break;
726         //Out of memory
727         case AUDIO_IO_ERROR_OUT_OF_MEMORY:
728                 return E_OUT_OF_MEMORY;
729                 break;
730         //Invalid parameter
731         case AUDIO_IO_ERROR_INVALID_PARAMETER:
732                 return E_INVALID_ARG;
733                 break;
734         //Invalid operation
735         case AUDIO_IO_ERROR_INVALID_OPERATION:
736                 return E_INVALID_OPERATION;
737                 break;
738         //Deviced not opened
739         case AUDIO_IO_ERROR_DEVICE_NOT_OPENED:
740                 return E_INVALID_STATE;
741                 break;
742         //Invalid Buffer
743         case AUDIO_IO_ERROR_INVALID_BUFFER:
744                 return E_INVALID_ARG;
745                 break;
746         //Device not Closed
747         case AUDIO_IO_ERROR_DEVICE_NOT_CLOSED:
748                 return E_INVALID_STATE;
749                 break;
750         //Sound policy error
751         case AUDIO_IO_ERROR_SOUND_POLICY:
752                 return E_DEVICE_BUSY;
753                 break;
754         default:
755                 return E_SYSTEM;
756                 break;
757         }
758 }
759
760 }}  //Tizen::Media