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