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