Merge "seek expection handling bug" into tizen_2.2
[platform/framework/native/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 std::unique_ptr<Tizen::Base::Runtime::Mutex> _AudioOutImpl::__pInstanceMutex;
57 bool _AudioOutImpl::__isInstanceMutexInitialized = false;
58
59 _AudioOutImpl::_AudioOutImpl(void)
60         : __pAudioOut(null)
61         , __pAudioOutEventListener(null)
62         , __audioOutState(AUDIOOUT_STATE_ERROR)
63         , __volume(-1)
64         , __volume256(-1)
65         , __presentSampleType(AUDIO_TYPE_NONE)
66         , __presentSampleRate(0)
67         , __audioOutHandle(null)
68         , __audioOutOptimalBufferSize(0)
69         , __stop(false)
70         , __interruptFlag(false)
71 {
72 }
73
74
75 _AudioOutImpl::~_AudioOutImpl(void)
76 {
77         if (__audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED)
78         {
79                 if (__audioOutState == AUDIOOUT_STATE_PLAYING )
80                 {
81                         this->Stop();
82                 }
83                 this->Reset();
84                 this->UnPrepare();
85         }
86         __pAudioOut = null;
87
88         if ((__audioOutState == AUDIOOUT_STATE_INITIALIZED ) || __audioOutState == AUDIOOUT_STATE_UNPREPARED )
89         {
90                 __pInstanceMutex->Acquire();
91                 instanceCount--;
92                 __pInstanceMutex->Release();
93         }
94 }
95
96 void
97 _AudioOutImpl::InitInstanceMutex(void)
98 {
99         result r = E_SUCCESS;
100         __pInstanceMutex.reset(new (std::nothrow) Tizen::Base::Runtime::Mutex);
101         SysTryReturn(NID_MEDIA, __pInstanceMutex.get() != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] no memory to create instance Mutex");
102         r = __pInstanceMutex->Create("FMEDIA_AUDIOOUT_N");
103         SysTryReturn(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Mutex::Create failed.");
104         __isInstanceMutexInitialized  = true;
105 }
106
107 _AudioOutImpl*
108 _AudioOutImpl::GetInstance(AudioOut* pAudioOut)
109 {
110         if (pAudioOut != null)
111         {
112                 return pAudioOut->__pAudioOutImpl;
113         }
114
115         return null;
116 }
117
118 const _AudioOutImpl*
119 _AudioOutImpl::GetInstance(const AudioOut* pAudioOut)
120 {
121         if (pAudioOut != null)
122         {
123                 return pAudioOut->__pAudioOutImpl;
124         }
125
126         return null;
127 }
128
129 result
130 _AudioOutImpl::Construct(const Tizen::Media::AudioOut* pAudioOut, Tizen::Media::IAudioOutEventListener& listener)
131 {
132         result r = E_SUCCESS;
133         __pAudioOut = const_cast <AudioOut*>(pAudioOut);
134         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
135         if (!__isInstanceMutexInitialized)
136         {
137                 pthread_once(&onceBlock, InitInstanceMutex);
138         }
139         SysTryCatch(NID_MEDIA, __isInstanceMutexInitialized == true, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] memory allocation for Instance Mutex failed");
140
141         if (!maxInstanceCount)
142         {
143                 r = MediaCapability::GetValue(AUDIOOUT_COUNT_MAX, maxInstanceCount);
144                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
145                 SysTryCatch(NID_MEDIA, maxInstanceCount > 0, , r, "[%s] Propagating.", GetErrorMessage(r));
146         }
147
148         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);
149
150         //Setting up the Events
151         __pAudioOutEvent.reset(new (std::nothrow) _AudioOutEvent);
152         SysTryReturnResult(NID_MEDIA, __pAudioOutEvent.get(), E_OUT_OF_MEMORY, "Memory allocation failed.");
153         r = __pAudioOutEvent->Construct(__pAudioOut);
154         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
155         r = __pAudioOutEvent->AddListener(listener);
156         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
157
158         //BufferQueue
159         r = __bufferQueue.Construct();
160         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
161         //Buffer Sync
162         __pBufferSync.reset( new (std::nothrow) Monitor);
163         SysTryCatch(NID_MEDIA, __pBufferSync.get() != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
164         r = __pBufferSync->Construct();
165         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
166
167         __volume = 50;
168         __volume256 = (__volume << 8) / 100;
169
170         __pInstanceMutex->Acquire();
171         instanceCount++;
172         __pInstanceMutex->Release();
173
174         __audioOutState = AUDIOOUT_STATE_INITIALIZED;
175         return E_SUCCESS;
176
177 CATCH:
178         __pAudioOut = null;
179         SetLastResult(r);
180         return r;
181 }
182
183 int
184 _AudioOutImpl::GetMaxBufferSize(void)
185 {
186         result r = E_SUCCESS;
187         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
188                 r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
189         return audioOutMaximumBufferSize;
190 CATCH:
191         SetLastResult(r);
192         return -1;
193 }
194
195 int
196 _AudioOutImpl::GetMinBufferSize(void)
197 {
198         result r = E_SUCCESS;
199         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
200                 r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
201         return audioOutMinimumBufferSize;
202 CATCH:
203         SetLastResult(r);
204         return -1;
205 }
206
207 AudioChannelType
208 _AudioOutImpl::GetOptimizedChannelType(void)
209 {
210         return audioOutOptimalChannelType;
211 }
212
213 int
214 _AudioOutImpl::GetOptimizedSampleRate(void)
215 {
216         result r = E_SUCCESS;
217         SetLastResult(r);
218         return audioOutOptimalSampleRate;
219 }
220
221 AudioSampleType
222 _AudioOutImpl::GetOptimizedSampleType(void)
223 {
224         return audioOutOptimalSampleType;
225 }
226
227 AudioOutState
228 _AudioOutImpl::GetState(void)
229 {
230         result r = E_SUCCESS;
231         SetLastResult(r);
232         SysLog(NID_MEDIA, "The current state of this instance is %d", __audioOutState);
233         return __audioOutState;
234 }
235
236 int
237 _AudioOutImpl::GetVolume(void) const
238 {
239         result r = E_SUCCESS;
240         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
241         r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
242         return __volume;
243 CATCH:
244         SetLastResult(r);
245         return -1;
246 }
247
248 result
249 _AudioOutImpl::SetVolume(int& volume)
250 {
251         result r = E_SUCCESS;
252         SysTryCatch(NID_MEDIA, __audioOutState < AUDIOOUT_STATE_UNPREPARED && __audioOutState >= AUDIOOUT_STATE_PREPARED,
253                 r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The state of this instance is in an invalid state.");
254         __volume = volume;
255         __volume256 = (__volume << 8) / 100;
256 CATCH:
257         return r;
258
259 }
260
261 result
262 _AudioOutImpl::Prepare(AudioSampleType audioSampleType, AudioChannelType audioChannelType, int audioSampleRate)
263 {
264         result r = E_SUCCESS;
265         int ret = 0;
266
267         SysTryReturnResult(NID_MEDIA, __audioOutState == AUDIOOUT_STATE_UNPREPARED || __audioOutState == AUDIOOUT_STATE_INITIALIZED,
268                 E_INVALID_STATE, "The state of this instance is in an invalid state.");
269         SysTryReturnResult(NID_MEDIA, audioSampleType >= AUDIO_TYPE_PCM_U8 && audioSampleType < AUDIO_TYPE_PCM_S16_BE, E_UNSUPPORTED_FORMAT,
270                 "Audio sample type is not valid.");
271         SysTryReturnResult(NID_MEDIA, audioChannelType == AUDIO_CHANNEL_TYPE_MONO || audioChannelType == AUDIO_CHANNEL_TYPE_STEREO, E_INVALID_ARG,
272                 "Invalid argument is used. Audio channel type is not valid");
273         SysTryReturnResult(NID_MEDIA, audioSampleRate >= 8000 && audioSampleRate <= 48000, E_INVALID_ARG,
274                 "Invalid argument is used. Audio sample rate is not valid.");
275
276         ret = audio_out_create(audioSampleRate, _AudioManagerConvert::ConvertChannelType(audioChannelType), _AudioManagerConvert::ConvertSampleType(audioSampleType), SOUND_TYPE_MEDIA, &__audioOutHandle);
277         r = MapExceptionToResult(ret);
278         SysTryCatch(NID_MEDIA, r != E_INVALID_STATE, , r, "[%s] The device has moved to invalid state as it has run out of system resources: 0x%x", GetErrorMessage(r), ret);
279         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_create operation with error code : 0x%x", GetErrorMessage(r), ret);
280
281         ret = audio_out_set_interrupted_cb(__audioOutHandle, AudioIoInterrupted, this);
282         r = MapExceptionToResult(ret);
283         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
284                 "[%s] Failed to perform audio_out_set_interrupted_cb operation with error code : 0x%x", GetErrorMessage(r), ret);
285
286         ret = audio_out_get_buffer_size(__audioOutHandle, &__audioOutOptimalBufferSize);
287         if (ret == AUDIO_IO_ERROR_NONE)
288         {
289                 SysLog(NID_MEDIA, "The optimal buffer size is %d", __audioOutOptimalBufferSize);
290         }
291         else
292         {
293                 r = MapExceptionToResult(ret);
294                 SysLogException(NID_MEDIA, r, "[%s] Failed to perform audio_out_get_buffer_size operation with error code : %x", GetErrorMessage(r), ret);
295         }
296         // this is done to get better Stop time
297         __audioOutOptimalBufferSize = 1024;
298         __pFeedBuffer.reset(new (std::nothrow) ByteBuffer);
299         __pFeedBuffer->Construct(__audioOutOptimalBufferSize);
300         __presentSampleType = audioSampleType;
301         __presentSampleRate = audioSampleRate;
302
303         __audioOutState = AUDIOOUT_STATE_PREPARED;
304         return r;
305 CATCH:
306         __audioOutHandle = null;
307         return r;
308 }
309
310 result
311 _AudioOutImpl::Prepare(AudioStreamType audioStreamType, AudioSampleType audioSampleType, AudioChannelType audioChannelType, int audioSampleRate)
312 {
313         result r = E_SUCCESS;
314         int ret = 0;
315
316         SysTryReturnResult(NID_MEDIA, __audioOutState == AUDIOOUT_STATE_UNPREPARED || __audioOutState == AUDIOOUT_STATE_INITIALIZED,
317                 E_INVALID_STATE, "The state of this instance is in an invalid state.");
318         SysTryReturnResult(NID_MEDIA, audioSampleType >= AUDIO_TYPE_PCM_U8 && audioSampleType < AUDIO_TYPE_PCM_S16_BE, E_UNSUPPORTED_FORMAT,
319                 "Audio sample type is not valid.");
320         SysTryReturnResult(NID_MEDIA, audioChannelType == AUDIO_CHANNEL_TYPE_MONO || audioChannelType == AUDIO_CHANNEL_TYPE_STEREO, E_INVALID_ARG,
321                 "Invalid argument is used. Audio channel type is not valid");
322         SysTryReturnResult(NID_MEDIA, audioSampleRate >= 8000 && audioSampleRate <= 48000, E_INVALID_ARG,
323                 "Invalid argument is used. Audio sample rate is not valid.");
324
325         ret = audio_out_create(audioSampleRate, _AudioManagerConvert::ConvertChannelType(audioChannelType), _AudioManagerConvert::ConvertSampleType(audioSampleType), _AudioManagerConvert::ConvertAudioStreamType2SoundType(audioStreamType), &__audioOutHandle);
326         r = MapExceptionToResult(ret);
327         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_create operation with error code : 0x%x", GetErrorMessage(r), ret);
328
329         ret = audio_out_prepare(__audioOutHandle);
330         r = MapExceptionToResult(ret);
331         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_prepare operation with error code : 0x%x", GetErrorMessage(r), ret);
332
333         ret = audio_out_set_interrupted_cb(__audioOutHandle, AudioIoInterrupted, this);
334         r = MapExceptionToResult(ret);
335         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);
336
337         ret = audio_out_get_buffer_size(__audioOutHandle, &__audioOutOptimalBufferSize);
338         if (ret == AUDIO_IO_ERROR_NONE)
339         {
340                 SysLog(NID_MEDIA, "The optimal buffer size is %d", __audioOutOptimalBufferSize);
341         }
342         else
343         {
344                 r = MapExceptionToResult(ret);
345                 SysLogException(NID_MEDIA, r, "[%s] Failed to perform audio_out_get_buffer_size operation with error code : %x", GetErrorMessage(r), ret);
346         }
347
348         __audioOutOptimalBufferSize = 1024;
349         __pFeedBuffer.reset(new (std::nothrow) ByteBuffer);
350         __pFeedBuffer->Construct(__audioOutOptimalBufferSize);
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         int feedSize = 0;
489         int index = 0;
490         while (!__stop)
491         {
492                 if (isSuccesful)
493                 {
494                         __pBufferSync->Enter();
495                         if ( __bufferQueue.Peek(pBuffer) == E_UNDERFLOW)
496                         {
497                                 //wait
498                                 __pBufferSync->Wait();
499                                 if (__stop)
500                                 {
501                                         __pBufferSync->Exit();
502                                         return this;
503                                 }
504                                 __bufferQueue.Peek(pBuffer);
505                         }
506                         __pBufferSync->Exit();
507
508                         SysTryCatch(NID_MEDIA, pBuffer, r = E_INVALID_ARG, E_INVALID_ARG,
509                                 "[E_INVALID_ARG] Invalid argument is used. The buffer to write is null.");
510                         isSuccesful = false;
511                 }
512
513                 buffer_size = pBuffer->GetLimit();
514                 pData = (unsigned char*) pBuffer->GetPointer();
515                 SysTryCatch(NID_MEDIA, pData, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument is used. The data to write is null");
516                 index = 0;
517                 while (!__stop && buffer_size)
518                 {
519                         if (buffer_size > __audioOutOptimalBufferSize)
520                         {
521                                 feedSize = __audioOutOptimalBufferSize;
522                                 buffer_size = buffer_size - __audioOutOptimalBufferSize;
523                                 SysLog(NID_MEDIA, "index - %d buffer_size - %d", index, feedSize);
524                         }
525                         else
526                         {
527                                 feedSize = buffer_size;
528                                 buffer_size = 0;
529                                 SysLog(NID_MEDIA, "index - %d buffer_size - %d", index, feedSize);
530                         }
531                         if ((__volume >= 0) && (__volume < 100))
532                         {
533                                 PreProcess(pBuffer, index, feedSize);
534                                 ret = audio_out_write(__audioOutHandle, (void*) __pFeedBuffer->GetPointer(), feedSize);
535                         }
536                         else
537                         {
538                                 pData = pData + index;
539                                 ret = audio_out_write(__audioOutHandle, (void*) pData, feedSize);
540                         }
541                         if (ret != feedSize)
542                         {
543                                 SysLog(NID_MEDIA, "The size of actual written data is %d", ret);
544                         }
545                         index = index + feedSize;
546                 }
547                 if (buffer_size == 0)
548                 {
549                         isSuccesful = true;
550                         if (!__stop)
551                         {
552                                 __pBufferSync->Enter();
553                                 __bufferQueue.Dequeue(pBuffer);
554                                 __pBufferSync->Exit();
555                                 pBuffer = NULL;
556                                 SendBufferEndReachedEvent();
557                         }
558                 }
559         }
560         return this;
561 CATCH:
562         return this;
563 }
564
565 void
566 _AudioOutImpl::AudioIoInterrupted(audio_io_interrupted_code_e code, void *pUserData)
567 {
568         SysTryReturn(NID_MEDIA, pUserData, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred. The value of pUserData is null.");
569         _AudioOutImpl *pAudioOutImpl = (_AudioOutImpl *)pUserData;
570
571         switch(code)
572         {
573         case AUDIO_IO_INTERRUPTED_COMPLETED:
574                 if (pAudioOutImpl->__audioOutState == AUDIOOUT_STATE_STOPPED)
575                 {
576                         if (!(pAudioOutImpl->__interruptFlag))
577                         {
578                                 pAudioOutImpl->SendReleased();
579                         }
580                         pAudioOutImpl->__interruptFlag = false;
581                 }
582                 break;
583         case AUDIO_IO_INTERRUPTED_BY_CALL:
584                 pAudioOutImpl->__interruptFlag = true;
585                 //Intentional Fall through
586         case AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG:
587                 //Intentional Fall through
588         case AUDIO_IO_INTERRUPTED_BY_MEDIA:
589                 //Intentional Fall through
590         case AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT:
591                 if (pAudioOutImpl->__audioOutState == AUDIOOUT_STATE_PLAYING)
592                 {
593                         pAudioOutImpl->SendAudioFocusChanged();
594                 }
595                 break;
596         case AUDIO_IO_INTERRUPTED_BY_ALARM:
597                 //Intentional Fall through
598         case AUDIO_IO_INTERRUPTED_BY_EMERGENCY:
599                 //Intentional Fall through
600         case AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA:
601                 if (pAudioOutImpl->__audioOutState == AUDIOOUT_STATE_PLAYING)
602                 {
603                         pAudioOutImpl->SendInterrupted();
604                 }
605                 break;
606         default:
607                 SysLog(NID_MEDIA, "Interrupt code obtained is wrong - %d", code);
608                 break;
609         }
610 }
611
612 result
613 _AudioOutImpl::SendBufferEndReachedEvent(void)
614 {
615         result r = E_SUCCESS;
616         _AudioOutEventArg* pAudioOutEventArg = null;
617         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
618         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
619
620         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_DATA_END_REACHED);
621         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
622         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
623         return r;
624 CATCH:
625         delete pAudioOutEventArg;
626         return r;
627 }
628
629 result
630 _AudioOutImpl::SendInterrupted()
631 {
632         result r = E_SUCCESS;
633         _AudioOutEventArg* pAudioOutEventArg = null;
634         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
635         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
636         this->Stop();
637         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_INTERRUPTED);
638         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
639         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
640         return r;
641 CATCH:
642         delete pAudioOutEventArg;
643         return r;
644 }
645
646 result
647 _AudioOutImpl::SendAudioFocusChanged()
648 {
649         result r = E_SUCCESS;
650         _AudioOutEventArg* pAudioOutEventArg = null;
651         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
652         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
653         this->Stop();
654         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_AUDIO_FOCUS_CHANGED);
655         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
656         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
657         return r;
658 CATCH:
659         delete pAudioOutEventArg;
660         return r;
661 }
662
663 result
664 _AudioOutImpl::SendReleased()
665 {
666         result r = E_SUCCESS;
667         _AudioOutEventArg* pAudioOutEventArg = null;
668         pAudioOutEventArg = new (std::nothrow) _AudioOutEventArg;
669         SysTryReturnResult(NID_MEDIA, pAudioOutEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
670         pAudioOutEventArg->SetEventType(_AUDIOOUT_EVENT_RELEASED);
671         r = __pAudioOutEvent->FireAsync(*pAudioOutEventArg);
672         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
673         return r;
674 CATCH:
675         delete pAudioOutEventArg;
676         return r;
677 }
678
679 void
680 _AudioOutImpl::ScaleDownVolume(unsigned char* pDataBuffer, int bytes)
681 {
682         switch (__presentSampleType)
683         {
684         case AUDIO_TYPE_PCM_U8:
685         {
686                 unsigned char* pOutput = __pFeedBuffer->GetPointer();
687                 unsigned char* pData = pDataBuffer;
688                 int noOfSamples = bytes;
689                 for (int i = 0; i < noOfSamples; i++)
690                 {
691                         int v = (((*pData++ - 128) * __volume256 + 128) >> 8) + 128;
692                         *pOutput++ = av_clip_uint8(v);
693                 }
694         }
695         break;
696
697         case AUDIO_TYPE_PCM_S16_LE:
698         {
699                 short* pData = (short*) pDataBuffer;
700                 short* pOutput = (short*) __pFeedBuffer->GetPointer();
701                 int noOfSamples = bytes >> 1;
702                 for (int i = 0; i < noOfSamples; i++)
703                 {
704                         int v = ((*pData++) * __volume256 + 128) >> 8;
705                         *pOutput++ = av_clip_int16(v);
706                 }
707         }
708         break;
709
710         default:
711                 break;
712         }
713 }
714
715 void
716 _AudioOutImpl::PreProcess(ByteBuffer* pBuffer, int index, int size)
717 {
718         unsigned char* pDataBuffer = null;
719         if (pBuffer->GetLimit() > 0)
720         {
721                 pDataBuffer = (unsigned char*) pBuffer->GetPointer();
722                 if (!pDataBuffer)
723                 {
724                         return;
725                 }
726                 pDataBuffer = pDataBuffer + index;
727         }
728         else
729         {
730                 return;
731         }
732         if ((__volume256 < 256) && (__volume256 >= 0))
733         {
734                 ScaleDownVolume(pDataBuffer, size);
735         }
736 }
737
738 result
739 _AudioOutImpl::MapExceptionToResult(int reason)
740 {
741         //All the fall through are intentional
742         switch (reason)
743         {
744         //Successful
745         case AUDIO_IO_ERROR_NONE:
746                 return E_SUCCESS;
747                 break;
748         //Out of memory
749         case AUDIO_IO_ERROR_OUT_OF_MEMORY:
750                 return E_OUT_OF_MEMORY;
751                 break;
752         //Invalid parameter
753         case AUDIO_IO_ERROR_INVALID_PARAMETER:
754                 return E_INVALID_ARG;
755                 break;
756         //Invalid operation
757         case AUDIO_IO_ERROR_INVALID_OPERATION:
758                 return E_INVALID_OPERATION;
759                 break;
760         //Deviced not opened
761         case AUDIO_IO_ERROR_DEVICE_NOT_OPENED:
762                 return E_INVALID_STATE;
763                 break;
764         //Invalid Buffer
765         case AUDIO_IO_ERROR_INVALID_BUFFER:
766                 return E_INVALID_ARG;
767                 break;
768         //Device not Closed
769         case AUDIO_IO_ERROR_DEVICE_NOT_CLOSED:
770                 return E_INVALID_STATE;
771                 break;
772         //Sound policy error
773         case AUDIO_IO_ERROR_SOUND_POLICY:
774                 return E_DEVICE_BUSY;
775                 break;
776         default:
777                 return E_SYSTEM;
778                 break;
779         }
780 }
781
782 }}  //Tizen::Media