Remove unused include statement
[platform/core/multimedia/libmm-sound.git] / server / plugin / wav / mm_sound_plugin_codec_wave.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 #include <stdint.h>
26
27 #include <semaphore.h>
28
29 #include <mm_error.h>
30 #include <mm_debug.h>
31 #include <pthread.h>
32 #include <mm_sound_pa_client.h>
33
34 #include "../../include/mm_sound_plugin_codec.h"
35 #include "../../../include/mm_sound_common.h"
36
37 #define SAMPLE_COUNT    128
38 #define WAV_FILE_SAMPLE_PLAY_DURATION           350                     /*Unit: ms*/
39 enum {
40         WAVE_CODE_UNKNOWN                               = 0,
41         WAVE_CODE_PCM                                   = 1,
42         WAVE_CODE_ADPCM                         = 2,
43         WAVE_CODE_G711                                  = 3,
44         WAVE_CODE_IMA_ADPCM                             = 17,
45         WAVE_CODE_G723_ADPCM                    = 20,
46         WAVE_CODE_GSM                                   = 49,
47         WAVE_CODE_G721_ADPCM                    = 64,
48         WAVE_CODE_MPEG                                  = 80,
49 };
50
51 #define MAKE_FOURCC(a, b, c, d)         ((a) | (b) << 8) | ((c) << 16 | ((d) << 24))
52 #define RIFF_CHUNK_ID                           ((uint32_t) MAKE_FOURCC('R', 'I', 'F', 'F'))
53 #define RIFF_CHUNK_TYPE                 ((uint32_t) MAKE_FOURCC('W', 'A', 'V', 'E'))
54 #define FMT_CHUNK_ID                            ((uint32_t) MAKE_FOURCC('f', 'm', 't', ' '))
55 #define DATA_CHUNK_ID                           ((uint32_t) MAKE_FOURCC('d', 'a', 't', 'a'))
56
57 #define CODEC_WAVE_LOCK(LOCK) do { pthread_mutex_lock(LOCK); } while (0)
58 #define CODEC_WAVE_UNLOCK(LOCK) do { pthread_mutex_unlock(LOCK); } while (0)
59
60 enum {
61    STATE_NONE = 0,
62    STATE_READY,
63    STATE_BEGIN,
64    STATE_PLAY,
65    STATE_STOP,
66 };
67
68 typedef struct
69 {
70         char *ptr_current;
71         int size;
72         int transper_size;
73         int handle;
74         int period;
75         int tone;
76         int keytone;
77         int repeat_count;
78         int (*stop_cb)(int);
79         int cb_param; // slotid
80         int state;
81         pthread_mutex_t mutex;
82         pthread_mutex_t *codec_wave_mutex;
83         int mode;
84         int volume_config;
85         int channels;
86         int samplerate;
87         int format;
88         int handle_route;
89         int priority;
90         MMSourceType *source;
91         char buffer[48000 / 1000 * SAMPLE_COUNT * 2 *2];//segmentation fault when above 22.05KHz stereo
92         int gain, out, in, option;
93         char stream_type[MM_SOUND_STREAM_TYPE_LEN];
94         int stream_index;
95 } wave_info_t;
96
97 static void _runing(void *param);
98
99 static int (*g_thread_pool_func)(void*, void (*)(void*)) = NULL;
100
101 int MMSoundPlugCodecWaveSetThreadPool(int (*func)(void*, void (*)(void*)))
102 {
103     debug_enter("(func : %p)\n", func);
104     g_thread_pool_func = func;
105     debug_leave("\n");
106     return MM_ERROR_NONE;
107 }
108
109 int* MMSoundPlugCodecWaveGetSupportTypes(void)
110 {
111     debug_enter("\n");
112     static int suported[2] = {MM_SOUND_SUPPORTED_CODEC_WAVE, 0};
113     debug_leave("\n");
114     return suported;
115 }
116
117 int MMSoundPlugCodecWaveParse(MMSourceType *source, mmsound_codec_info_t *info)
118 {
119         struct __riff_chunk
120         {
121                 uint32_t chunkid;
122                 uint32_t chunksize;
123                 uint32_t rifftype;
124         };
125
126         struct __wave_chunk
127         {
128                 uint32_t chunkid;
129                 uint32_t chunksize;
130                 uint16_t compression;
131                 uint16_t channels;
132                 uint32_t samplerate;
133                 uint32_t avgbytepersec;
134                 uint16_t blockkalign;
135                 uint16_t bitspersample;
136         };
137
138         struct __data_chunk
139         {
140                 uint32_t chunkid;
141                 uint32_t chunkSize;
142         };
143
144         struct __riff_chunk *priff = NULL;
145         struct __wave_chunk *pwav = NULL;
146         struct __data_chunk *pdata = NULL;
147 //      struct __fmt_chunk *pfmt = NULL;
148
149         int datalen = -1;
150         char *data = NULL;
151         unsigned int tSize;
152
153         debug_enter("\n");
154
155         data = MMSourceGetPtr(source);
156         debug_msg("[CODEC WAV] source ptr :[%p]\n", data);
157
158         datalen = MMSourceGetCurSize(source);
159         debug_msg("[CODEC WAV] source size :[0x%08X]\n", datalen);
160
161         priff = (struct __riff_chunk *) data;
162
163         /* Must be checked, Just for wav or not */
164         if (priff->chunkid != RIFF_CHUNK_ID ||priff->rifftype != RIFF_CHUNK_TYPE)
165                 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
166
167         if(priff->chunksize != datalen -8)
168                 priff->chunksize = (datalen-8);
169
170         if (priff->chunkid != RIFF_CHUNK_ID ||priff->chunksize != datalen -8 ||priff->rifftype != RIFF_CHUNK_TYPE) {
171                 debug_msg("[CODEC WAV] This contents is not RIFF file\n");
172                 debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %ld, rifftype : 0x%lx\n", priff->chunkid, priff->chunksize, priff->rifftype);
173                 //debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %d, rifftype : 0x%lx\n", RIFF_CHUNK_ID, datalen-8, RIFF_CHUNK_TYPE);
174                 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
175         }
176
177         debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %ld, rifftype : 0x%lx\n", priff->chunkid, priff->chunksize, priff->rifftype);
178         //debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %d, rifftype : 0x%lx\n", RIFF_CHUNK_ID, datalen-8, RIFF_CHUNK_TYPE);
179
180         tSize = sizeof(struct __riff_chunk);
181         pdata = (struct __data_chunk*)(data+tSize);
182
183         while (pdata->chunkid != FMT_CHUNK_ID && tSize < datalen) {
184                 tSize += (pdata->chunkSize+8);
185
186                 if (tSize >= datalen) {
187                         debug_warning("[CODEC WAV] Parsing finished : unable to find the Wave Format chunk\n");
188                         return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
189                 } else {
190                         pdata = (struct __data_chunk*)(data+tSize);
191                 }
192         }
193         pwav = (struct __wave_chunk*)(data+tSize);
194
195         if (pwav->chunkid != FMT_CHUNK_ID ||
196             pwav->compression != WAVE_CODE_PCM ||       /* Only supported PCM */
197             pwav->avgbytepersec != pwav->samplerate * pwav->blockkalign ||
198             pwav->blockkalign != (pwav->bitspersample >> 3)*pwav->channels) {
199                 debug_msg("[CODEC WAV] This contents is not supported wave file\n");
200                 debug_msg("[CODEC WAV] chunkid : 0x%lx, comp : 0x%x, av byte/sec : %lu, blockalign : %d\n", pwav->chunkid, pwav->compression, pwav->avgbytepersec, pwav->blockkalign);
201                 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
202         }
203
204         /* Only One data chunk support */
205
206         tSize += (pwav->chunksize+8);
207         pdata = (struct __data_chunk *)(data+tSize);
208
209         while (pdata->chunkid != DATA_CHUNK_ID && tSize < datalen) {
210                 tSize += (pdata->chunkSize+8);
211                 if (tSize >= datalen) {
212                         debug_warning("[CODEC WAV] Parsing finished : unable to find the data chunk\n");
213                         return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
214                 } else {
215                         pdata = (struct __data_chunk*)(data+tSize);
216                 }
217         }
218
219         info->codec = MM_SOUND_SUPPORTED_CODEC_WAVE;
220         info->channels = pwav->channels;
221         info->format = pwav->bitspersample;
222         info->samplerate = pwav->samplerate;
223         info->doffset = (tSize+8);
224         info->size = pdata->chunkSize;
225         info->duration = ((info->size)*1000)/pwav->avgbytepersec;
226         debug_msg("info->size:%d info->duration: %d\n", info->size, info->duration);
227
228         debug_leave("\n");
229         return MM_ERROR_NONE;
230 }
231
232
233
234 int MMSoundPlugCodecWaveCreate(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle)
235 {
236         wave_info_t* p = NULL;
237         MMSourceType *source;
238         static int keytone_period = 0;
239
240 #ifdef DEBUG_DETAIL
241         debug_enter("\n");
242 #endif
243
244         debug_msg("period[%d] type[%s] ch[%d] format[%d] rate[%d] doffset[%d] priority[%d] repeat[%d] volume[%f] callback[%p] route[%d]\n",
245                         keytone_period, (info->codec == MM_SOUND_SUPPORTED_CODEC_WAVE) ? "Wave" : "Unknown",
246                         info->channels, info->format, info->samplerate, info->doffset, param->priority, param->repeat_count,
247                         param->volume, param->stop_cb, param->handle_route);
248         source = param->source;
249
250         if (g_thread_pool_func == NULL) {
251                 debug_error("[CODEC WAV] Need thread pool!\n");
252                 return MM_ERROR_SOUND_INTERNAL;
253         }
254
255         p = (wave_info_t *) malloc(sizeof(wave_info_t));
256
257         if (p == NULL) {
258                 debug_error("[CODEC WAV] memory allocation failed\n");
259                 return MM_ERROR_OUT_OF_MEMORY;
260         }
261
262         memset(p, 0, sizeof(wave_info_t));
263         p->handle = 0;
264
265         p->ptr_current = MMSourceGetPtr(source) + info->doffset;
266
267         p->size = info->size;
268         p->transper_size = info->samplerate / 1000 * SAMPLE_COUNT * (info->format >> 3) * info->channels;
269
270         p->tone = param->tone;
271         p->repeat_count = param ->repeat_count;
272         p->stop_cb = param->stop_cb;
273         p->cb_param = param->param;
274         p->source = source;
275         p->codec_wave_mutex = param->codec_wave_mutex;
276         p->stream_index = param->stream_index;
277         MMSOUND_STRNCPY(p->stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
278         //      pthread_mutex_init(&p->mutex, NULL);
279
280         debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size);
281         debug_msg("[CODEC WAV] size : %d\n", p->size);
282
283         if(info->duration < WAV_FILE_SAMPLE_PLAY_DURATION) {
284                 p->mode = HANDLE_MODE_OUTPUT_LOW_LATENCY;
285         } else {
286                 p->mode = HANDLE_MODE_OUTPUT;
287         }
288
289         p->priority = param->priority;
290         p->volume_config = param->volume_config;
291         p->channels = info->channels;
292         p->samplerate = info->samplerate;
293
294         p->handle_route = param->handle_route;
295
296         switch(info->format)
297         {
298         case 8:
299                 p->format =  PA_SAMPLE_U8;
300                 break;
301         case 16:
302                 p->format =  PA_SAMPLE_S16LE;
303                 break;
304         default:
305                 p->format =  PA_SAMPLE_S16LE;
306                 break;
307         }
308
309         debug_msg("[CODEC WAV] PARAM mode : [%d]\n", p->mode);
310         debug_msg("[CODEC WAV] PARAM channels : [%d]\n", p->channels);
311         debug_msg("[CODEC WAV] PARAM samplerate : [%d]\n", p->samplerate);
312         debug_msg("[CODEC WAV] PARAM format : [%d]\n", p->format);
313         debug_msg("[CODEC WAV] PARAM volume type : [%x]\n", p->volume_config);
314
315         p->state = STATE_READY;
316
317         g_thread_pool_func(p, _runing);
318         debug_msg("[CODEC WAV] Thread pool start\n");
319         *handle = (MMHandleType)p;
320
321 #ifdef DEBUG_DETAIL
322         debug_leave("\n");
323 #endif
324
325         return MM_ERROR_NONE;
326 }
327
328
329 int MMSoundPlugCodecWavePlay(MMHandleType handle)
330 {
331         wave_info_t *p = (wave_info_t *) handle;
332
333         debug_enter("(handle %x)\n", handle);
334
335         if (p->size <= 0) {
336                 debug_error("[CODEC WAV] end of file\n");
337                 return MM_ERROR_END_OF_FILE;
338         }
339         debug_msg("[CODEC WAV] send start signal\n");
340         p->state = STATE_BEGIN;
341
342         debug_leave("\n");
343
344         return MM_ERROR_NONE;
345 }
346
347 static void _runing(void *param)
348 {
349         wave_info_t *p = (wave_info_t*) param;
350         int nread = 0;
351         char *org_cur = NULL;
352         int org_size = 0;
353         char *dummy = NULL;
354         int size;
355
356         pa_sample_spec ss;
357         mm_sound_handle_route_info route_info;
358
359         if (p == NULL) {
360                 debug_error("[CODEC WAV] param is null\n");
361                 return;
362         }
363
364         debug_enter("[CODEC WAV] (Slot ID %d)\n", p->cb_param);
365         CODEC_WAVE_LOCK(p->codec_wave_mutex);
366
367         route_info.policy = HANDLE_ROUTE_POLICY_OUT_AUTO;
368
369         ss.rate = p->samplerate;
370         ss.channels = p->channels;
371         ss.format = p->format;
372         p->period = pa_sample_size(&ss) * ((ss.rate * 25) / 1000);
373         p->handle = mm_sound_pa_open(p->mode, &route_info, p->priority, p->volume_config, &ss, NULL, &size, p->stream_type, p->stream_index);
374         if(!p->handle) {
375                 debug_critical("[CODEC WAV] Can not open audio handle\n");
376                 CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
377                 return;
378         }
379
380         if (p->handle == 0) {
381                 debug_critical("[CODEC WAV] audio_handle is not created !! \n");
382                 CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
383                 free(p);
384                 p = NULL;
385                 return;
386         }
387
388         /* Set the thread schedule */
389         org_cur = p->ptr_current;
390         org_size = p->size;
391
392         dummy = malloc(p->period);
393         if(!dummy) {
394                 debug_error("[CODEC WAV] not enough memory");
395                 CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
396                 return;
397         }
398         memset(dummy, 0, p->period);
399         p->transper_size = p->period;
400         /* stop_size = org_size > p->period ? org_size : p->period; */
401
402         debug_msg("[CODEC WAV] Wait start signal\n");
403
404         while(p->state == STATE_READY) {
405                 usleep(4);
406         }
407
408         debug_msg("[CODEC WAV] Recv start signal\n");
409         debug_msg("[CODEC WAV] repeat : %d\n", p->repeat_count);
410         debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size);
411
412         if (p->state != STATE_STOP) {
413                 debug_msg("[CODEC WAV] Play start\n");
414                 p->state = STATE_PLAY;
415         } else {
416                 debug_warning ("[CODEC WAV] state is already STATE_STOP\n");
417         }
418
419         while (((p->repeat_count == -1)?(1):(p->repeat_count--)) && p->state == STATE_PLAY) {
420                 while (p->state == STATE_PLAY && p->size > 0) {
421                         if (p->size >= p->transper_size) {
422                                 nread = p->transper_size;
423                                 memcpy(p->buffer, p->ptr_current, nread);
424                                 mm_sound_pa_write(p->handle, p->buffer, nread);
425                                 p->ptr_current += nread;
426                                 p->size -= nread;
427                                 debug_msg("[CODEC WAV] Playing, nRead_data : %d Size : %d \n", nread, p->size);
428                         } else {
429                                 /* Write remain size */
430                                 nread = p->size;
431                                 memcpy(p->buffer, p->ptr_current, nread);
432                                 mm_sound_pa_write(p->handle, p->buffer, nread);
433                                 mm_sound_pa_write(p->handle, dummy, (p->transper_size-nread));
434                                 p->ptr_current += nread;
435                                 p->size = 0;
436                         }
437                 }
438                 p->ptr_current = org_cur;
439                 p->size = org_size;
440         }
441
442         debug_msg("[CODEC WAV] End playing\n");
443         p->state = STATE_STOP;
444
445         if (p->handle == 0) {
446                 usleep(200000);
447                 debug_warning("[CODEC WAV] audio already unrealize !!\n");
448         } else {
449                 /* usleep(75000); */
450                 if(MM_ERROR_NONE != mm_sound_pa_drain(p->handle))
451                         debug_error("mm_sound_pa_drain() failed\n");
452
453                 if(MM_ERROR_NONE != mm_sound_pa_close(p->handle)) {
454                         debug_error("[CODEC WAV] Can not close audio handle\n");
455                 } else {
456                         p->handle = 0;
457                 }
458         }
459         CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
460
461         p->handle = 0;
462
463         p->state = STATE_NONE;
464
465         free(dummy); dummy = NULL;
466         if (p->stop_cb)
467         {
468                 debug_msg("[CODEC WAV] Play is finished, Now start callback\n");
469                 p->stop_cb(p->cb_param);
470         }
471         debug_leave("\n");
472 }
473
474
475 int MMSoundPlugCodecWaveStop(MMHandleType handle)
476 {
477         wave_info_t *p = (wave_info_t*) handle;
478
479         if (!p) {
480                 debug_error("The handle is null\n");
481                 return MM_ERROR_SOUND_INTERNAL;
482         }
483         debug_msg("[CODEC WAV] Current state is state %d\n", p->state);
484         debug_msg("[CODEC WAV] Handle 0x%08X stop requested\n", handle);
485
486         p->state = STATE_STOP;
487
488     return MM_ERROR_NONE;
489 }
490
491 int MMSoundPlugCodecWaveDestroy(MMHandleType handle)
492 {
493         wave_info_t *p = (wave_info_t*) handle;
494
495         if (!p) {
496                 debug_warning("Can not destroy handle :: handle is invalid");
497                 return MM_ERROR_SOUND_INVALID_POINTER;
498         }
499
500         if(p->source) {
501                 mm_source_close(p->source);
502                 free(p->source); p->source = NULL;
503         }
504
505         free(p); p = NULL;
506
507         return MM_ERROR_NONE;
508 }
509
510 EXPORT_API
511 int MMSoundGetPluginType(void)
512 {
513     return MM_SOUND_PLUGIN_TYPE_CODEC;
514 }
515
516 EXPORT_API
517 int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf)
518 {
519     intf->GetSupportTypes   = MMSoundPlugCodecWaveGetSupportTypes;
520     intf->Parse             = MMSoundPlugCodecWaveParse;
521     intf->Create            = MMSoundPlugCodecWaveCreate;
522     intf->Destroy           = MMSoundPlugCodecWaveDestroy;
523     intf->Play              = MMSoundPlugCodecWavePlay;
524     intf->Stop              = MMSoundPlugCodecWaveStop;
525     intf->SetThreadPool     = MMSoundPlugCodecWaveSetThreadPool;
526
527     return MM_ERROR_NONE;
528 }
529
530