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.
27 #include <semaphore.h>
33 #include <mm_sound_pa_client.h>
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 #include "../../../include/mm_sound_common.h"
42 #define SAMPLE_COUNT 128
43 #define WAV_FILE_SAMPLE_PLAY_DURATION 350 /*Unit: ms*/
45 WAVE_CODE_UNKNOWN = 0,
49 WAVE_CODE_IMA_ADPCM = 17,
50 WAVE_CODE_G723_ADPCM = 20,
52 WAVE_CODE_G721_ADPCM = 64,
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'))
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)
84 int cb_param; // slotid
86 pthread_mutex_t mutex;
87 pthread_mutex_t *codec_wave_mutex;
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];
102 static void _runing(void *param);
104 static int (*g_thread_pool_func)(void*, void (*)(void*)) = NULL;
106 int MMSoundPlugCodecWaveSetThreadPool(int (*func)(void*, void (*)(void*)))
108 debug_enter("(func : %p)\n", func);
109 g_thread_pool_func = func;
111 return MM_ERROR_NONE;
114 int* MMSoundPlugCodecWaveGetSupportTypes(void)
117 static int suported[2] = {MM_SOUND_SUPPORTED_CODEC_WAVE, 0};
122 int MMSoundPlugCodecWaveParse(MMSourceType *source, mmsound_codec_info_t *info)
135 uint16_t compression;
138 uint32_t avgbytepersec;
139 uint16_t blockkalign;
140 uint16_t bitspersample;
149 struct __riff_chunk *priff = NULL;
150 struct __wave_chunk *pwav = NULL;
151 struct __data_chunk *pdata = NULL;
152 // struct __fmt_chunk *pfmt = NULL;
160 data = MMSourceGetPtr(source);
161 debug_msg("[CODEC WAV] source ptr :[%p]\n", data);
163 datalen = MMSourceGetCurSize(source);
164 debug_msg("[CODEC WAV] source size :[0x%08X]\n", datalen);
166 priff = (struct __riff_chunk *) data;
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;
172 if(priff->chunksize != datalen -8)
173 priff->chunksize = (datalen-8);
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;
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);
185 tSize = sizeof(struct __riff_chunk);
186 pdata = (struct __data_chunk*)(data+tSize);
188 while (pdata->chunkid != FMT_CHUNK_ID && tSize < datalen) {
189 tSize += (pdata->chunkSize+8);
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;
195 pdata = (struct __data_chunk*)(data+tSize);
198 pwav = (struct __wave_chunk*)(data+tSize);
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;
209 /* Only One data chunk support */
211 tSize += (pwav->chunksize+8);
212 pdata = (struct __data_chunk *)(data+tSize);
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;
220 pdata = (struct __data_chunk*)(data+tSize);
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);
234 return MM_ERROR_NONE;
239 int MMSoundPlugCodecWaveCreate(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle)
241 wave_info_t* p = NULL;
242 MMSourceType *source;
243 static int keytone_period = 0;
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;
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));
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 p->codec_wave_mutex = param->codec_wave_mutex;
281 p->stream_index = param->stream_index;
282 MMSOUND_STRNCPY(p->stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
283 // pthread_mutex_init(&p->mutex, NULL);
285 debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size);
286 debug_msg("[CODEC WAV] size : %d\n", p->size);
288 if(info->duration < WAV_FILE_SAMPLE_PLAY_DURATION) {
289 p->mode = HANDLE_MODE_OUTPUT_LOW_LATENCY;
291 p->mode = HANDLE_MODE_OUTPUT;
294 p->priority = param->priority;
295 p->volume_config = param->volume_config;
296 p->channels = info->channels;
297 p->samplerate = info->samplerate;
299 p->handle_route = param->handle_route;
304 p->format = PA_SAMPLE_U8;
307 p->format = PA_SAMPLE_S16LE;
310 p->format = PA_SAMPLE_S16LE;
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);
320 p->state = STATE_READY;
322 g_thread_pool_func(p, _runing);
323 debug_msg("[CODEC WAV] Thread pool start\n");
324 *handle = (MMHandleType)p;
330 return MM_ERROR_NONE;
334 int MMSoundPlugCodecWavePlay(MMHandleType handle)
336 wave_info_t *p = (wave_info_t *) handle;
338 debug_enter("(handle %x)\n", handle);
341 debug_error("[CODEC WAV] end of file\n");
342 return MM_ERROR_END_OF_FILE;
344 debug_msg("[CODEC WAV] send start signal\n");
345 p->state = STATE_BEGIN;
349 return MM_ERROR_NONE;
352 static void _runing(void *param)
354 wave_info_t *p = (wave_info_t*) param;
356 char *org_cur = NULL;
362 mm_sound_handle_route_info route_info;
365 debug_error("[CODEC WAV] param is null\n");
369 debug_enter("[CODEC WAV] (Slot ID %d)\n", p->cb_param);
370 CODEC_WAVE_LOCK(p->codec_wave_mutex);
372 route_info.policy = HANDLE_ROUTE_POLICY_OUT_AUTO;
374 ss.rate = p->samplerate;
375 ss.channels = p->channels;
376 ss.format = p->format;
377 p->period = pa_sample_size(&ss) * ((ss.rate * 25) / 1000);
378 p->handle = mm_sound_pa_open(p->mode, &route_info, p->priority, p->volume_config, &ss, NULL, &size, p->stream_type, p->stream_index);
380 debug_critical("[CODEC WAV] Can not open audio handle\n");
381 CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
385 if (p->handle == 0) {
386 debug_critical("[CODEC WAV] audio_handle is not created !! \n");
387 CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
393 /* Set the thread schedule */
394 org_cur = p->ptr_current;
397 dummy = malloc(p->period);
399 debug_error("[CODEC WAV] not enough memory");
400 CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
403 memset(dummy, 0, p->period);
404 p->transper_size = p->period;
405 /* stop_size = org_size > p->period ? org_size : p->period; */
407 debug_msg("[CODEC WAV] Wait start signal\n");
409 while(p->state == STATE_READY) {
413 debug_msg("[CODEC WAV] Recv start signal\n");
414 debug_msg("[CODEC WAV] repeat : %d\n", p->repeat_count);
415 debug_msg("[CODEC WAV] transper_size : %d\n", p->transper_size);
417 if (p->state != STATE_STOP) {
418 debug_msg("[CODEC WAV] Play start\n");
419 p->state = STATE_PLAY;
421 debug_warning ("[CODEC WAV] state is already STATE_STOP\n");
424 while (((p->repeat_count == -1)?(1):(p->repeat_count--)) && p->state == STATE_PLAY) {
425 while (p->state == STATE_PLAY && p->size > 0) {
426 if (p->size >= p->transper_size) {
427 nread = p->transper_size;
428 memcpy(p->buffer, p->ptr_current, nread);
429 mm_sound_pa_write(p->handle, p->buffer, nread);
430 p->ptr_current += nread;
432 debug_msg("[CODEC WAV] Playing, nRead_data : %d Size : %d \n", nread, p->size);
434 /* Write remain size */
436 memcpy(p->buffer, p->ptr_current, nread);
437 mm_sound_pa_write(p->handle, p->buffer, nread);
438 mm_sound_pa_write(p->handle, dummy, (p->transper_size-nread));
439 p->ptr_current += nread;
443 p->ptr_current = org_cur;
447 debug_msg("[CODEC WAV] End playing\n");
448 p->state = STATE_STOP;
450 if (p->handle == 0) {
452 debug_warning("[CODEC WAV] audio already unrealize !!\n");
455 if(MM_ERROR_NONE != mm_sound_pa_drain(p->handle))
456 debug_error("mm_sound_pa_drain() failed\n");
458 if(MM_ERROR_NONE != mm_sound_pa_close(p->handle)) {
459 debug_error("[CODEC WAV] Can not close audio handle\n");
464 CODEC_WAVE_UNLOCK(p->codec_wave_mutex);
468 p->state = STATE_NONE;
470 free(dummy); dummy = NULL;
473 debug_msg("[CODEC WAV] Play is finished, Now start callback\n");
474 p->stop_cb(p->cb_param);
480 int MMSoundPlugCodecWaveStop(MMHandleType handle)
482 wave_info_t *p = (wave_info_t*) handle;
485 debug_error("The handle is null\n");
486 return MM_ERROR_SOUND_INTERNAL;
488 debug_msg("[CODEC WAV] Current state is state %d\n", p->state);
489 debug_msg("[CODEC WAV] Handle 0x%08X stop requested\n", handle);
491 p->state = STATE_STOP;
493 return MM_ERROR_NONE;
496 int MMSoundPlugCodecWaveDestroy(MMHandleType handle)
498 wave_info_t *p = (wave_info_t*) handle;
501 debug_warning("Can not destroy handle :: handle is invalid");
502 return MM_ERROR_SOUND_INVALID_POINTER;
506 mm_source_close(p->source);
507 free(p->source); p->source = NULL;
512 return MM_ERROR_NONE;
516 int MMSoundGetPluginType(void)
518 return MM_SOUND_PLUGIN_TYPE_CODEC;
522 int MMSoundPlugCodecGetInterface(mmsound_codec_interface_t *intf)
524 intf->GetSupportTypes = MMSoundPlugCodecWaveGetSupportTypes;
525 intf->Parse = MMSoundPlugCodecWaveParse;
526 intf->Create = MMSoundPlugCodecWaveCreate;
527 intf->Destroy = MMSoundPlugCodecWaveDestroy;
528 intf->Play = MMSoundPlugCodecWavePlay;
529 intf->Stop = MMSoundPlugCodecWaveStop;
530 intf->SetThreadPool = MMSoundPlugCodecWaveSetThreadPool;
532 return MM_ERROR_NONE;