4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Seungbae Shin <seungbae.shin@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include <semaphore.h>
32 #include <avsys-audio.h>
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_hal.h"
39 #include "../../../include/mm_sound_private.h"
42 #define SAMPLE_COUNT 128
44 WAVE_CODE_UNKNOWN = 0,
48 WAVE_CODE_IMA_ADPCM = 17,
49 WAVE_CODE_G723_ADPCM = 20,
51 WAVE_CODE_G721_ADPCM = 64,
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'))
74 avsys_handle_t audio_handle;
82 pthread_mutex_t mutex;
84 char buffer[48000 / 1000 * SAMPLE_COUNT * 2 *2];//segmentation fault when above 22.05KHz stereo
88 static void _runing(void *param);
90 static int (*g_thread_pool_func)(void*, void (*)(void*)) = NULL;
92 int MMSoundPlugCodecWaveSetThreadPool(int (*func)(void*, void (*)(void*)))
94 debug_enter("(func : %p)\n", func);
95 g_thread_pool_func = func;
100 int* MMSoundPlugCodecWaveGetSupportTypes(void)
103 static int suported[2] = {MM_SOUND_SUPPORTED_CODEC_WAVE, 0};
108 int MMSoundPlugCodecWaveParse(MMSourceType *source, mmsound_codec_info_t *info)
121 unsigned short compression;
122 unsigned short channels;
123 unsigned long samplerate;
124 unsigned long avgbytepersec;
125 unsigned short blockkalign;
126 unsigned short bitspersample;
135 struct __riff_chunk *priff = NULL;
136 struct __wave_chunk *pwav = NULL;
137 struct __data_chunk *pdata = NULL;
138 // struct __fmt_chunk *pfmt = NULL;
146 data = MMSourceGetPtr(source);
147 debug_msg("[CODEC WAV] source ptr :[%p]\n", data);
149 datalen = MMSourceGetCurSize(source);
150 debug_msg("[CODEC WAV] source size :[0x%08X]\n", datalen);
152 priff = (struct __riff_chunk *) data;
154 /* Must be checked, Just for wav or not */
155 if (priff->chunkid != RIFF_CHUNK_ID ||priff->rifftype != RIFF_CHUNK_TYPE)
156 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
158 if(priff->chunksize != datalen -8)
159 priff->chunksize = (datalen-8);
161 if (priff->chunkid != RIFF_CHUNK_ID ||priff->chunksize != datalen -8 ||priff->rifftype != RIFF_CHUNK_TYPE) {
162 debug_msg("[CODEC WAV] This contents is not RIFF file\n");
163 debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %ld, rifftype : 0x%lx\n", priff->chunkid, priff->chunksize, priff->rifftype);
164 //debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %d, rifftype : 0x%lx\n", RIFF_CHUNK_ID, datalen-8, RIFF_CHUNK_TYPE);
165 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
168 debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %ld, rifftype : 0x%lx\n", priff->chunkid, priff->chunksize, priff->rifftype);
169 //debug_msg("[CODEC WAV] cunkid : %ld, chunksize : %d, rifftype : 0x%lx\n", RIFF_CHUNK_ID, datalen-8, RIFF_CHUNK_TYPE);
171 tSize = sizeof(struct __riff_chunk);
172 pdata = (struct __data_chunk*)(data+tSize);
174 while (pdata->chunkid != FMT_CHUNK_ID && tSize < datalen) {
175 tSize += (pdata->chunkSize+8);
177 if (tSize >= datalen) {
178 debug_warning("[CODEC WAV] Parsing finished : unable to find the Wave Format chunk\n");
179 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
181 pdata = (struct __data_chunk*)(data+tSize);
184 pwav = (struct __wave_chunk*)(data+tSize);
186 if (pwav->chunkid != FMT_CHUNK_ID ||
187 pwav->compression != WAVE_CODE_PCM || /* Only supported PCM */
188 pwav->avgbytepersec != pwav->samplerate * pwav->blockkalign ||
189 pwav->blockkalign != (pwav->bitspersample >> 3)*pwav->channels) {
190 debug_msg("[CODEC WAV] This contents is not supported wave file\n");
191 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);
192 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
195 /* Only One data chunk support */
197 tSize += (pwav->chunksize+8);
198 pdata = (struct __data_chunk *)(data+tSize);
200 while (pdata->chunkid != DATA_CHUNK_ID && tSize < datalen) {
201 tSize += (pdata->chunkSize+8);
202 if (tSize >= datalen) {
203 debug_warning("[CODEC WAV] Parsing finished : unable to find the data chunk\n");
204 return MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
206 pdata = (struct __data_chunk*)(data+tSize);
210 info->codec = MM_SOUND_SUPPORTED_CODEC_WAVE;
211 info->channels = pwav->channels;
212 info->format = pwav->bitspersample;
213 info->samplerate = pwav->samplerate;
214 info->doffset = (tSize+8);
215 info->size = pdata->chunkSize;
216 debug_msg("info->size:%d\n", info->size);
219 return MM_ERROR_NONE;
224 int MMSoundPlugCodecWaveCreate(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle)
226 int ret = MM_ERROR_NONE;
227 wave_info_t* p = NULL;
229 avsys_audio_param_t audio_param;
231 static avsys_handle_t keytone_handle = (avsys_handle_t)-1;
232 MMSourceType *source;
234 static int keytone_period = 0;
237 debug_msg("[CODEC WAV] Local keytone_period : %d\n", keytone_period);
238 debug_msg("[CODEC WAV] Local keytone_handle : %d\n", (int)keytone_handle);
240 debug_msg("[CODEC WAV] Type %s\n", info->codec == MM_SOUND_SUPPORTED_CODEC_WAVE ? "PCM Wave" : "Unknown");
241 debug_msg("[CODEC WAV] channels : %d\n", info->channels);
242 debug_msg("[CODEC WAV] format : %d\n", info->format);
243 debug_msg("[CODEC WAV] samplerate : %d\n", info->samplerate);
244 debug_msg("[CODEC WAV] doffset : %d\n", info->doffset);
246 debug_msg("[CODEC WAV] priority : %d\n", param->priority);
247 debug_msg("[CODEC WAV] repeat : %d\n", param->repeat_count);
248 debug_msg("[CODEC WAV] volume type : %d\n", param->volume);
249 debug_msg("[CODEC WAV] callback : %p\n", param->stop_cb);
250 debug_msg("[CODEC WAV] Keytonemode : %08x\n", param->keytone);
251 debug_msg("[CODEC WAV] handle route : %d\n", param->handle_route);
253 source = param->source;
255 if (g_thread_pool_func == NULL) {
256 debug_error("[CODEC WAV] Need thread pool!\n");
257 return MM_ERROR_SOUND_INTERNAL;
260 p = (wave_info_t *) malloc(sizeof(wave_info_t));
263 debug_error("[CODEC WAV] memory allocation failed\n");
264 return MM_ERROR_OUT_OF_MEMORY;
267 memset(p, 0, sizeof(wave_info_t));
268 p->audio_handle = (avsys_handle_t)-1;
270 p->ptr_current = MMSourceGetPtr(source) + info->doffset;
272 p->size = info->size;
273 p->transper_size = info->samplerate / 1000 * SAMPLE_COUNT * (info->format >> 3) * info->channels;
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;
280 // pthread_mutex_init(&p->mutex, NULL);
282 debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size);
283 debug_msg("[CODEC WAV] size : %d\n", p->size);
286 /* audio param setting */
287 memset (&audio_param, 0, sizeof(avsys_audio_param_t));
288 audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT;
289 audio_param.priority = param->priority;
290 audio_param.vol_type = param->volume_config;
291 audio_param.channels = info->channels;
292 audio_param.samplerate = info->samplerate;
293 if(param->handle_route == MM_SOUND_HANDLE_ROUTE_USING_CURRENT) /* normal, solo */
294 audio_param.handle_route = AVSYS_AUDIO_HANDLE_ROUTE_FOLLOWING_POLICY;
296 audio_param.handle_route = AVSYS_AUDIO_HANDLE_ROUTE_HANDSET_ONLY;
297 p->handle_route = param->handle_route;
302 audio_param.format = AVSYS_AUDIO_FORMAT_8BIT;
305 audio_param.format = AVSYS_AUDIO_FORMAT_16BIT;
308 audio_param.format = AVSYS_AUDIO_FORMAT_16BIT;
312 debug_msg("[CODEC WAV] PARAM mode : [%d]\n", audio_param.mode);
313 debug_msg("[CODEC WAV] PARAM priority: [%d]\n", audio_param.priority);
314 debug_msg("[CODEC WAV] PARAM channels : [%d]\n", audio_param.channels);
315 debug_msg("[CODEC WAV] PARAM samplerate : [%d]\n", audio_param.samplerate);
316 debug_msg("[CODEC WAV] PARAM format : [%d]\n", audio_param.format);
317 debug_msg("[CODEC WAV] PARAM volume type : [%x]\n", audio_param.vol_type);
319 ret = avsys_audio_open(&audio_param, &p->audio_handle, &p->period);
320 if (ret != MM_ERROR_NONE)
321 debug_critical("[CODEC WAV] Can not open audio handle\n");
325 if (p->audio_handle == (avsys_handle_t)-1) {
326 debug_critical("[CODEC WAV] audio_handle is not created !! \n");
329 return MM_ERROR_SOUND_INTERNAL;
333 p->state = STATE_READY;
335 g_thread_pool_func(p, _runing);
336 debug_msg("[CODEC WAV] Thread pool start\n");
337 *handle = (MMHandleType)p;
341 return MM_ERROR_NONE;
345 int MMSoundPlugCodecWavePlay(MMHandleType handle)
347 wave_info_t *p = (wave_info_t *) handle;
349 debug_enter("(handle %x)\n", handle);
352 debug_error("[CODEC WAV] end of file\n");
353 return MM_ERROR_END_OF_FILE;
355 debug_msg("[CODEC WAV] send start signal\n");
356 p->state = STATE_BEGIN;
360 return MM_ERROR_NONE;
365 static void _runing(void *param)
367 wave_info_t *p = (wave_info_t*) param;
369 char *org_cur = NULL;
374 int gain, out, in, option;
375 int gain_after, out_after, in_after, option_after;
378 debug_enter("[CODEC WAV] (Slot ID %d)\n", p->cb_param);
380 /* Set the thread schedule */
381 org_cur = p->ptr_current;
384 dummy = malloc(p->period);
386 debug_error("[CODEC WAV] not enough memory");
389 memset(dummy, 0, p->period);
390 p->transper_size = p->period;
392 debug_msg("[CODEC WAV] Wait start signal\n");
394 while(p->state == STATE_READY)
400 switch(p->handle_route)
402 case MM_SOUND_HANDLE_ROUTE_SPEAKER:
403 case MM_SOUND_HANDLE_ROUTE_SPEAKER_NO_RESTORE:
404 debug_msg("[CODEC WAV] Save backup path\n");
405 avsys_audio_get_path_ex(&gain, &out, &in, &option);
407 /* if current out is not speaker, then force set path to speaker */
408 if (out != AVSYS_AUDIO_PATH_EX_SPK) {
409 debug_msg("[CODEC WAV] current out is not SPEAKER, set path to SPEAKER now!!!\n");
410 audio_hal_set_sound_path(AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER, AVSYS_AUDIO_PATH_EX_SPK, AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_OPTION_NONE);
413 case MM_SOUND_HANDLE_ROUTE_USING_CURRENT:
418 debug_msg("[CODEC WAV] Recv start signal\n");
419 debug_msg("[CODEC WAV] repeat : %d\n", p->repeat_count);
420 debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size);
422 if (p->state != STATE_STOP) {
423 debug_msg("[CODEC WAV] Play start\n");
424 p->state = STATE_PLAY;
426 debug_warning ("[CODEC WAV] state is already STATE_STOP\n");
429 while (((p->repeat_count == -1)?(1):(p->repeat_count--)) && p->state == STATE_PLAY) {
430 while (p->state == STATE_PLAY && p->size > 0) {
431 if (p->size >= p->transper_size) {
432 nread = p->transper_size;
433 memcpy(p->buffer, p->ptr_current, nread);
434 avsys_audio_write(p->audio_handle, p->buffer, nread);
435 p->ptr_current += nread;
437 debug_msg("[CODEC WAV] Playing, nRead_data : %d Size : %d \n", nread, p->size);
439 /* Write remain size */
441 memcpy(p->buffer, p->ptr_current, nread);
442 avsys_audio_write(p->audio_handle, p->buffer, nread);
443 avsys_audio_write(p->audio_handle, dummy, (p->transper_size-nread));
444 //avsys_audio_drain(p->audio_handle);
445 //debug_error("Drain is called\n");
446 p->ptr_current += nread;
450 p->ptr_current = org_cur;
454 debug_msg("[CODEC WAV] End playing\n");
455 p->state = STATE_STOP;
457 if (p->audio_handle == (avsys_handle_t)-1) {
459 debug_warning("[CODEC WAV] audio already unrealize !!\n");
463 if(AVSYS_FAIL(avsys_audio_drain(p->audio_handle)))
465 debug_error("avsys_audio_drain() failed\n");
471 if (p->handle_route == MM_SOUND_HANDLE_ROUTE_SPEAKER) {
472 avsys_audio_get_path_ex(&gain_after, &out_after, &in_after, &option_after);
474 /* If current path is not same as before playing sound, restore the sound path */
475 if (gain_after != gain || out_after != out || in_after != in || option_after != option) {
477 debug_msg("[CODEC WAV] Restore path to previous one\n");
478 if (audio_hal_set_sound_path(gain, out, in, option)) {
479 debug_error("[CODEC WAV] Can not restore sound path\n");
484 ret = avsys_audio_close(p->audio_handle);
485 if (AVSYS_FAIL(ret)) {
486 debug_critical("[CODEC WAV] Can not close audio handle\n");
490 p->audio_handle = (avsys_handle_t)-1;
492 p->state = STATE_NONE;
497 debug_msg("[CODEC WAV] Play is finished, Now start callback\n");
498 p->stop_cb(p->cb_param);
504 int MMSoundPlugCodecWaveStop(MMHandleType handle)
506 wave_info_t *p = (wave_info_t*) handle;
508 debug_error("The handle is NULL\n");
509 return MM_ERROR_SOUND_INTERNAL;
511 debug_msg("[CODEC WAV] Current state is state %d\n", p->state);
512 debug_msg("[CODEC WAV] Handle 0x%08X stop requested\n", handle);
514 p->state = STATE_STOP;
516 return MM_ERROR_NONE;
519 int MMSoundPlugCodecWaveDestroy(MMHandleType handle)
521 wave_info_t *p = (wave_info_t*) handle;
524 debug_warning("Can not destroy handle :: handle is null\n");
525 return MM_ERROR_SOUND_INVALID_POINTER;
529 mm_source_close(p->source);
535 return MM_ERROR_NONE;
539 int MMSoundGetPluginType(void)
541 return MM_SOUND_PLUGIN_TYPE_CODEC;
545 int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf)
547 intf->GetSupportTypes = MMSoundPlugCodecWaveGetSupportTypes;
548 intf->Parse = MMSoundPlugCodecWaveParse;
549 intf->Create = MMSoundPlugCodecWaveCreate;
550 intf->Destroy = MMSoundPlugCodecWaveDestroy;
551 intf->Play = MMSoundPlugCodecWavePlay;
552 intf->Stop = MMSoundPlugCodecWaveStop;
553 intf->SetThreadPool = MMSoundPlugCodecWaveSetThreadPool;
555 return MM_ERROR_NONE;