Remove unused include statement
[platform/core/multimedia/libmm-sound.git] / server / plugin / ogg / mm_sound_plugin_codec_ogg.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <semaphore.h>
27 #include <pthread.h>
28
29 #include <mm_error.h>
30 #include <mm_debug.h>
31 #include <tremolo_vorbisdec_api.h>
32
33 #include "../../include/mm_sound.h"
34 #include "../../include/mm_sound_plugin_codec.h"
35 #include "../../../include/mm_sound_pa_client.h"
36
37 #define OGG_DEC_BUF_SIZE 4096
38 #define OGG_FILE_SAMPLE_PLAY_DURATION 290
39
40 #define TIME_MSEC (1000)
41 #define SILENT_SND_MIN_VALUE (90)
42 #define CODEC_OGG_LOCK(LOCK) do { pthread_mutex_lock(LOCK); } while (0)
43 #define CODEC_OGG_UNLOCK(LOCK) do { pthread_mutex_unlock(LOCK); } while (0)
44
45 int MMSoundPlugCodecOggStop(MMHandleType handle);
46
47 enum {
48    STATE_NONE = 0,
49    STATE_READY,
50    STATE_BEGIN,
51    STATE_PLAY,
52    STATE_ENDOFDECORD,
53    STATE_STOP,
54 };
55
56 typedef struct {
57         /* thread controls */
58         sem_t                   start_wave_signal; /* control start of pcm write thread */
59         sem_t                   start_ogg_signal; /* control start of ogg decord thread*/
60         pthread_mutex_t         mutex;
61
62      /* Codec infomations */
63         void                    *decoder;
64         char* pcm_out_buf;
65         int                     offset;
66         int     period;
67         int     handle_route;
68         int gain, out, in, option;
69         mm_sound_device_in device_in;
70         mm_sound_device_out device_out;
71         unsigned int volume_value;
72
73      /* Audio Infomations */
74         int                             transper_size; /* audio open return */
75         int                             handle;
76
77      /* control Informations */
78         int                             repeat_count;
79         int                             (*stop_cb)(int);
80         int                             cb_param;
81         int                             state;
82         MMSourceType         *source;
83         int codec;
84         int NumberOfChannels;
85         int SamplingFrequency;
86         int format;
87         int Duration;
88         int BitRate;
89         int BufferSize;
90 } ogg_info_t;
91
92 static int (*g_thread_pool_func)(void*, void (*)(void*)) = NULL;
93
94 void _pcm_out_func(void *data)
95 {
96         ogg_info_t *p = (ogg_info_t*) data;
97         int used_size;
98         int decoded_len;
99         unsigned char* ogg_buf;
100         unsigned int ogg_remain;
101         int err;
102
103         debug_enter("\n");
104
105         sem_wait(&p->start_wave_signal);
106         ogg_buf = MMSourceGetPtr(p->source);
107         ogg_remain = MMSourceGetCurSize(p->source);
108
109         while (p->state == STATE_PLAY) {
110                 err = OGGDEC_FrameDecode(p->decoder, ogg_buf+p->offset, &used_size, p->pcm_out_buf, &decoded_len);
111                 if (decoded_len > 0) {
112                         mm_sound_pa_write(p->handle, p->pcm_out_buf, decoded_len);
113                         ogg_buf += used_size;
114                         ogg_remain -= used_size;
115                         if(err != OGGDEC_SUCCESS) {
116                                 MMSoundPlugCodecOggStop((MMHandleType)p);
117                                 debug_error("Decode done :: %d\n", err);
118                                 break;
119                         }
120                 } else {
121                         MMSoundPlugCodecOggStop((MMHandleType)p);
122                         break;
123                 }
124         }
125
126         mm_sound_pa_drain(p->handle);
127         mm_sound_pa_close(p->handle);
128
129         /* Notice */
130         /* OggDestory is called by stop_cb func */
131         /* INDEED the stop_cb must be called, after end of all progress */
132         if(p->stop_cb) {
133                 p->stop_cb(p->cb_param);
134         }
135         debug_leave("\n");
136 }
137
138 int MMSoundPlugCodecOggSetThreadPool(int (*func)(void*, void (*)(void*)))
139 {
140         debug_enter("(func : %p)\n", func);
141         g_thread_pool_func = func;
142         debug_leave("\n");
143         return MM_ERROR_NONE;
144 }
145
146 int* MMSoundPlugCodecOggGetSupportTypes(void)
147 {
148         debug_enter("\n");
149         static int suported[2] = {MM_SOUND_SUPPORTED_CODEC_OGG, 0};
150         debug_leave("\n");
151         return suported;
152 }
153
154 int MMSoundPlugCodecOggParse(MMSourceType *source, mmsound_codec_info_t *info)
155 {
156         unsigned char *ptr = NULL;
157         unsigned int size = 0;
158         int err;
159         OGG_DEC_INFO ogg_info;
160
161         debug_enter("\n");
162
163         ptr = (unsigned char*)MMSourceGetPtr(source);
164         size = MMSourceGetCurSize(source);
165         debug_msg("[CODEC OGG] source ptr :[0x%08X] ::: source size :[0x%d]\n", ptr, size);
166
167         err = OGGDEC_PreparseDecode(ptr, size, &ogg_info);
168         if (err != OGGDEC_SUCCESS) {
169                 debug_error("Not valid Ogg data format");
170                 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
171         }
172
173         info->format = 16;
174         info->channels = ogg_info.channels;
175         info->samplerate = ogg_info.samplerate;
176         info->duration = ogg_info.duration;
177         info->codec = MM_AUDIO_CODEC_OGG;
178         debug_msg("[CODEC OGG]Channels %d  Samplerate %d\n", ogg_info.channels, ogg_info.samplerate);
179         debug_leave("\n");
180
181         return MM_ERROR_NONE;
182 }
183
184 int MMSoundPlugCodecOggCreate(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle)
185 {
186         ogg_info_t* p = NULL;
187         MMSourceType *source = NULL;
188         OGG_DEC_INFO ogg_info;
189         int err, used_size, skipsize;
190         int ret = MM_ERROR_NONE;
191
192         mm_sound_handle_route_info route_info;
193         route_info.policy = HANDLE_ROUTE_POLICY_OUT_AUTO;
194
195         pa_sample_spec ss;
196         int size = 0;
197         int mode = HANDLE_MODE_OUTPUT_LOW_LATENCY;
198
199         debug_enter("\n");
200
201         if (g_thread_pool_func == NULL) {
202                 debug_error("Need thread pool!\n");
203                 return MM_ERROR_SOUND_INTERNAL;
204         }
205
206         source = param->source;
207         debug_msg("[CODEC OGG]Param source p 0x08%X\n", param->source);
208
209         p = (ogg_info_t *) malloc(sizeof(ogg_info_t));
210         if (p == NULL) {
211                 debug_error("[CODEC OGG]Memory allocation Fail\n");
212                 return MM_ERROR_OUT_OF_MEMORY;
213         }
214
215         memset(p, 0, sizeof(ogg_info_t));
216         p->source = param->source;
217         p->BufferSize = MMSourceGetCurSize(source);
218
219         pthread_mutex_init(&p->mutex, NULL);
220
221         err = sem_init(&p->start_ogg_signal, 0, 0);
222         if (err == -1) {
223                 debug_error("[CODEC OGG]Semaphore init fail\n");
224                 ret = MM_ERROR_SOUND_INTERNAL;
225                 goto error_before_create;
226         }
227
228         err = sem_init(&p->start_wave_signal, 0, 0);
229         if (err == -1) {
230                 debug_error("[CODEC OGG]Semaphore init fail\n");
231                 sem_destroy(&p->start_ogg_signal);
232                 ret = MM_ERROR_SOUND_INTERNAL;
233                 goto error_before_create;
234         }
235
236         err = OGGDEC_CreateDecode(&p->decoder);
237         if (err != OGGDEC_SUCCESS) {
238                 debug_error("[CODEC OGG]Fail to Create ogg decoder\n");
239                 ret = MM_ERROR_SOUND_INTERNAL;
240                 goto error_before_create;
241         }
242         p->pcm_out_buf = (char *)malloc(sizeof(char)*OGG_DEC_BUF_SIZE);
243         if (p->pcm_out_buf == NULL) {
244                 debug_error("[CODEC OGG]Memory allocation fail\n");
245                 ret = MM_ERROR_SOUND_NO_FREE_SPACE;
246                 goto error_after_create;
247         }
248         err = OGGDEC_InitDecode(p->decoder, (unsigned char*)p->source->ptr, p->BufferSize, &skipsize);
249         if (err != OGGDEC_SUCCESS) {
250                 debug_error("Fail to init ogg decoder\n");
251                 ret = MM_ERROR_SOUND_INTERNAL;
252                 goto error_after_buffer;
253         }
254         p->offset = skipsize;
255
256         err = OGGDEC_InfoDecode(p->decoder, p->source->ptr+p->offset, &used_size, &ogg_info);
257         if (err != OGGDEC_SUCCESS) {
258                 debug_error("[CODEC OGG]Fail to get ogg info\n");
259                 ret = MM_ERROR_SOUND_INTERNAL;
260                 goto error_after_buffer;
261         }
262         p->offset += used_size;
263         p->Duration = info->duration;
264         p->format = info->format = 16;
265         info->channels = ogg_info.channels;
266         info->samplerate = ogg_info.samplerate;
267
268         /* Temporal code for debug */
269         /*
270         debug_msg("([CODEC OGG]handle %x)\n", p);
271         debug_msg("[CODEC OGG]Type %s\n", info->codec == MM_AUDIO_CODEC_OGG ? "OGG" : "Unknown");
272         debug_msg("[CODEC OGG]channels   : %d\n", info->channels);
273         debug_msg("[CODEC OGG]format     : %d\n", info->format);
274         debug_msg("[CODEC OGG]samplerate : %d\n", info->samplerate);
275         debug_msg("[CODEC OGG]doffset    : %d\n", info->doffset);
276         debug_msg("[CODEC OGG]priority : %d\n", param->priority);
277         debug_msg("[CODEC OGG]repeat : %d\n", param->repeat_count);
278         debug_msg("[CODEC OGG]volume : %d\n", param->volume);
279         debug_msg("[CODEC OGG]callback : %08x\n", param->stop_cb);
280         */
281         debug_msg("Audio duration [%d]", info->duration);
282         p->repeat_count = param ->repeat_count;
283         p->stop_cb = param->stop_cb;
284         p->cb_param = param->param;
285
286         if(info->duration < OGG_FILE_SAMPLE_PLAY_DURATION) {
287                 mode = HANDLE_MODE_OUTPUT_LOW_LATENCY;
288         } else {
289                 mode = HANDLE_MODE_OUTPUT;
290         }
291
292         route_info.policy = HANDLE_ROUTE_POLICY_OUT_AUTO;
293
294         p->handle_route = param->handle_route;
295
296         switch(info->format)
297         {
298         case 8:
299                 ss.format = PA_SAMPLE_U8;
300                 break;
301         case 16:
302                 ss.format =  PA_SAMPLE_S16LE;
303                 break;
304         default:
305                 ss.format =  PA_SAMPLE_S16LE;
306                 break;
307         }
308         ss.channels = info->channels;
309         ss.rate = info->samplerate;
310
311         debug_msg("[CODEC OGG] PARAM mode:[%d] priority:[%d] policy:[%d] channels:[%d] samplerate:[%d] format:[%d] volume type:[%x]\n",
312                 mode,-1, route_info.policy, ss.channels, ss.rate, ss.format, param->volume_config);
313
314         p->handle = mm_sound_pa_open(HANDLE_MODE_OUTPUT_LOW_LATENCY, &route_info, 0, param->volume_config, &ss, NULL, &size, param->stream_type, param->stream_index);
315         if(!p->handle) {
316                 debug_error("[CODEC OGG] Can not open audio handle\n");
317                 ret = MM_ERROR_SOUND_INTERNAL;
318                 goto error_after_buffer;
319         }
320
321         pthread_mutex_lock(&p->mutex);
322         p->state = STATE_READY;
323         pthread_mutex_unlock(&p->mutex);
324         *handle = p;
325
326         err = g_thread_pool_func(p, _pcm_out_func);
327         if (err) {
328                 debug_error("[CODEC OGG]pthread_create() fail in pcm thread\n");
329                 ret = MM_ERROR_SOUND_INTERNAL;
330                 goto error_after_buffer;
331         }
332
333         debug_leave("\n");
334         return MM_ERROR_NONE;
335
336 error_after_buffer:
337         free(p->pcm_out_buf);
338
339 error_after_create:
340         sem_destroy(&p->start_ogg_signal);
341         sem_destroy(&p->start_wave_signal);
342         OGGDEC_ResetDecode(p->decoder);
343         OGGDEC_DeleteDecode(p->decoder);
344
345 error_before_create:
346         free(p);
347         return ret;
348 }
349
350 int MMSoundPlugCodecOggPlay(MMHandleType handle)
351 {
352         ogg_info_t *p = (ogg_info_t *) handle;
353         debug_enter("(handle %x)\n", handle);
354
355         if (p->BufferSize <= 0) {
356             debug_error("[CODEC OGG]End of file\n");
357             return MM_ERROR_END_OF_FILE;
358         }
359         pthread_mutex_lock(&p->mutex);
360         p->state = STATE_PLAY;
361         pthread_mutex_unlock(&p->mutex);
362         sem_post(&p->start_wave_signal);
363
364         debug_leave("\n");
365         return MM_ERROR_NONE;
366 }
367
368 int MMSoundPlugCodecOggStop(MMHandleType handle)
369 {
370         ogg_info_t *p = (ogg_info_t *) handle;
371         debug_enter("(handle %x)\n", handle);
372         pthread_mutex_lock(&p->mutex);
373         p->state = STATE_STOP;
374         pthread_mutex_unlock(&p->mutex);
375         debug_leave("\n");
376
377         return MM_ERROR_NONE;
378 }
379
380 int MMSoundPlugCodecOggDestroy(MMHandleType handle)
381 {
382         ogg_info_t *p = (ogg_info_t*) handle;
383         int err;
384
385         debug_enter("(handle %x)\n", handle);
386
387         if (!p) {
388                 debug_critical("Confirm the hadle (is NULL)\n");
389                 err = MM_ERROR_SOUND_INTERNAL;
390                 return err;
391         }
392
393         if(p->source) {
394                 mm_source_close(p->source);
395                 free(p->source); p->source = NULL;
396         }
397
398         err = OGGDEC_ResetDecode(p->decoder);
399         if (err != OGGDEC_SUCCESS) {
400                 debug_error("[CODEC OGG]Codec Reset fail\n");
401                 err = MM_ERROR_SOUND_INTERNAL;
402         }
403
404         err = OGGDEC_DeleteDecode(p->decoder);
405         if (err != OGGDEC_SUCCESS)      {
406                 debug_error("[CODEC OGG]Delete Decode fail\n");
407                 err = MM_ERROR_SOUND_INTERNAL;
408         }
409
410         sem_destroy(&p->start_wave_signal);
411         sem_destroy(&p->start_ogg_signal);
412
413         if(p->pcm_out_buf) {
414                 free(p->pcm_out_buf);
415                 p->pcm_out_buf = NULL;
416         }
417
418         if (p) {
419                 free (p);
420                 p = NULL;
421         }
422
423         debug_leave("\n");
424         return err;
425 }
426
427 EXPORT_API
428 int MMSoundGetPluginType(void)
429 {
430         debug_enter("\n");
431         debug_leave("\n");
432         return MM_SOUND_PLUGIN_TYPE_CODEC;
433 }
434
435 EXPORT_API
436 int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf)
437 {
438         debug_enter("\n");
439         if (!intf) {
440                 debug_critical("Confirm the codec interface struct (is NULL)\n");
441                 return MM_ERROR_SOUND_INTERNAL;
442         }
443
444         intf->GetSupportTypes   = MMSoundPlugCodecOggGetSupportTypes;
445         intf->Parse             = MMSoundPlugCodecOggParse;
446         intf->Create            = MMSoundPlugCodecOggCreate;
447         intf->Destroy           = MMSoundPlugCodecOggDestroy;
448         intf->Play              = MMSoundPlugCodecOggPlay;
449         intf->Stop              = MMSoundPlugCodecOggStop;
450         intf->SetThreadPool     = MMSoundPlugCodecOggSetThreadPool;
451
452         debug_leave("\n");
453         return MM_ERROR_NONE;
454 }