4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jeongmo Yang <jm80.yang@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.
22 /*=======================================================================================
24 =======================================================================================*/
26 #include <mm_sound_private.h>
27 #include <audio-session-manager.h>
28 #include "mm_camcorder_internal.h"
29 #include "mm_camcorder_sound.h"
31 /*---------------------------------------------------------------------------------------
32 | GLOBAL VARIABLE DEFINITIONS for internal |
33 ---------------------------------------------------------------------------------------*/
35 /*---------------------------------------------------------------------------------------
36 | LOCAL VARIABLE DEFINITIONS for internal |
37 ---------------------------------------------------------------------------------------*/
38 #define BLOCK_SIZE 2048
40 /*---------------------------------------------------------------------------------------
41 | LOCAL FUNCTION PROTOTYPES: |
42 ---------------------------------------------------------------------------------------*/
43 static gboolean __prepare_buffer(SOUND_INFO *info, char *filename);
44 static gboolean __cleanup_buffer(SOUND_INFO *info);
45 static void *__sound_open_thread_func(void *data);
46 static void *__sound_write_thread_func(void *data);
47 static void __solo_sound_callback(void *data);
49 static gboolean __prepare_buffer(SOUND_INFO *info, char *filename)
51 mmf_return_val_if_fail(info, FALSE);
52 mmf_return_val_if_fail(filename, FALSE);
54 info->infile = sf_open(filename, SFM_READ, &info->sfinfo);
55 if (!(info->infile)) {
56 _mmcam_dbg_err("failed to open file [%s]", filename);
60 _mmcam_dbg_log("SOUND: frame = %lld", info->sfinfo.frames);
61 _mmcam_dbg_log("SOUND: sameplerate = %d", info->sfinfo.samplerate);
62 _mmcam_dbg_log("SOUND: channel = %d", info->sfinfo.channels);
63 _mmcam_dbg_log("SOUND: format = 0x%x", info->sfinfo.format);
65 info->pcm_size = info->sfinfo.frames * info->sfinfo.channels * 2;
66 info->pcm_buf = (short *)malloc(info->pcm_size);
67 if (info->pcm_buf == NULL) {
68 _mmcam_dbg_err("pcm_buf malloc failed");
69 sf_close(info->infile);
73 sf_read_short(info->infile, info->pcm_buf, info->pcm_size);
79 static gboolean __cleanup_buffer(SOUND_INFO *info)
81 mmf_return_val_if_fail(info, FALSE);
84 sf_close(info->infile);
93 _mmcam_dbg_log("Done");
99 static void *__sound_open_thread_func(void *data)
102 system_audio_route_t route = SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY;
103 SOUND_INFO *info = NULL;
104 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
106 mmf_return_val_if_fail(hcamcorder, NULL);
108 MMTA_ACUM_ITEM_BEGIN(" __sound_open_thread_func", FALSE);
110 info = &(hcamcorder->snd_info);
112 __ta__(" __prepare_buffer",
113 ret = __prepare_buffer(info, info->filename);
119 __ta__(" mm_sound_pcm_play_open",
120 ret = mm_sound_pcm_play_open_ex(&(info->handle), info->sfinfo.samplerate,
121 (info->sfinfo.channels == 1) ? MMSOUND_PCM_MONO : MMSOUND_PCM_STEREO,
122 MMSOUND_PCM_S16_LE, VOLUME_TYPE_FIXED, ASM_EVENT_EXCLUSIVE_MMSOUND);
126 _mmcam_dbg_err("mm_sound_pcm_play_open failed [%x]", ret);
127 __cleanup_buffer(info);
131 info->state = _MMCAMCORDER_SOUND_STATE_PREPARE;
132 _mmcam_dbg_log("mm_sound_pcm_play_open succeeded. state [%d]", info->state);
135 ret = mm_sound_route_get_system_policy(&route);
136 if (ret != MM_ERROR_NONE) {
137 _mmcam_dbg_err("mm_sound_route_get_system_policy failed [%x]", ret);
141 _mmcam_dbg_log("current policy [%d]", route);
143 if (route != SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY) {
144 ret = mm_sound_route_set_system_policy(SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY);
145 if (ret != MM_ERROR_NONE) {
146 _mmcam_dbg_err("mm_sound_route_set_system_policy failed [%x]", ret);
150 info->route_policy_backup = route;
154 pthread_cond_signal(&(info->open_cond));
155 pthread_mutex_unlock(&(info->open_mutex));
157 _mmcam_dbg_log("Done");
159 MMTA_ACUM_ITEM_END(" __sound_open_thread_func", FALSE);
164 pthread_mutex_unlock(&(info->open_mutex));
165 _mmcamcorder_sound_finalize((MMHandleType)hcamcorder);
171 static void *__sound_write_thread_func(void *data)
174 int bytes_to_write = 0;
175 int remain_bytes = 0;
176 system_audio_route_t route = SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY;
177 char *buffer_to_write = NULL;
178 SOUND_INFO *info = NULL;
179 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
181 mmf_return_val_if_fail(hcamcorder, NULL);
183 info = &(hcamcorder->snd_info);
185 _mmcam_dbg_log("RUN sound write thread");
187 pthread_mutex_lock(&(info->play_mutex));
190 pthread_cond_wait(&(info->play_cond), &(info->play_mutex));
192 _mmcam_dbg_log("Signal received. Play sound.");
194 if (info->thread_run == FALSE) {
195 _mmcam_dbg_log("Exit thread command is detected");
199 ret = mm_sound_route_get_system_policy(&route);
200 if (ret != MM_ERROR_NONE) {
201 _mmcam_dbg_err("get_system_policy failed [%x]. skip sound play.", ret);
205 _mmcam_dbg_log("current policy [%d]", route);
207 if (route != SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY) {
208 ret = mm_sound_route_set_system_policy(SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY);
209 if (ret != MM_ERROR_NONE) {
210 _mmcam_dbg_err("set_system_policy failed. skip sound play.");
214 info->route_policy_backup = route;
217 buffer_to_write = (char *)info->pcm_buf;
218 remain_bytes = info->pcm_size;
221 while (remain_bytes) {
222 bytes_to_write = (remain_bytes >= BLOCK_SIZE) ? BLOCK_SIZE : remain_bytes;
223 ret = mm_sound_pcm_play_write(info->handle, buffer_to_write, bytes_to_write);
224 if (ret != bytes_to_write) {
225 _mmcam_dbg_err("pcm write error [%x]", ret);
227 remain_bytes -= bytes_to_write;
228 buffer_to_write += bytes_to_write;
232 pthread_mutex_unlock(&(info->play_mutex));
234 _mmcam_dbg_log("END sound write thread");
240 gboolean _mmcamcorder_sound_init(MMHandleType handle, char *filename)
243 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
244 SOUND_INFO *info = NULL;
246 mmf_return_val_if_fail(hcamcorder, FALSE);
248 info = &(hcamcorder->snd_info);
250 pthread_mutex_lock(&(info->open_mutex));
252 if (info->state > _MMCAMCORDER_SOUND_STATE_NONE) {
253 _mmcam_dbg_warn("already initialized [%d]", info->state);
254 pthread_mutex_unlock(&(info->open_mutex));
258 if (info->filename) {
259 free(info->filename);
260 info->filename = NULL;
263 info->filename = strdup(filename);
264 if (info->filename == NULL) {
265 _mmcam_dbg_err("strdup failed");
268 pthread_mutex_init(&(info->play_mutex), NULL);
269 pthread_cond_init(&(info->play_cond), NULL);
270 if (pthread_create(&(info->thread), NULL, __sound_write_thread_func, (void *)handle) == 0) {
271 info->thread_run = TRUE;
272 info->state = _MMCAMCORDER_SOUND_STATE_INIT;
273 info->route_policy_backup = -1;
274 _mmcam_dbg_log("write thread created");
277 _mmcam_dbg_err("failed to create write thread");
278 free(info->filename);
279 info->filename = NULL;
284 pthread_mutex_unlock(&(info->open_mutex));
290 gboolean _mmcamcorder_sound_prepare(MMHandleType handle)
293 pthread_t open_thread;
294 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
295 SOUND_INFO *info = NULL;
297 mmf_return_val_if_fail(hcamcorder, FALSE);
299 info = &(hcamcorder->snd_info);
301 pthread_mutex_lock(&(info->open_mutex));
303 if (info->state == _MMCAMCORDER_SOUND_STATE_INIT) {
304 if (pthread_create(&open_thread, NULL, __sound_open_thread_func, (void *)handle) == 0) {
305 _mmcam_dbg_log("open thread created");
308 _mmcam_dbg_err("failed to create open thread");
310 pthread_mutex_unlock(&(info->open_mutex));
313 _mmcam_dbg_warn("Wrong state [%d]", info->state);
315 pthread_mutex_unlock(&(info->open_mutex));
322 gboolean _mmcamcorder_sound_play(MMHandleType handle)
324 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
325 SOUND_INFO *info = NULL;
327 mmf_return_val_if_fail(hcamcorder, FALSE);
329 info = &(hcamcorder->snd_info);
331 pthread_mutex_lock(&(info->open_mutex));
333 if (info->state < _MMCAMCORDER_SOUND_STATE_PREPARE) {
334 _mmcam_dbg_log("not initialized state:[%d]", info->state);
335 pthread_mutex_unlock(&(info->open_mutex));
339 _mmcam_dbg_log("Play start");
341 pthread_mutex_lock(&(info->play_mutex));
342 pthread_cond_signal(&(info->play_cond));
343 pthread_mutex_unlock(&(info->play_mutex));
345 pthread_mutex_unlock(&(info->open_mutex));
347 _mmcam_dbg_log("Done");
353 gboolean _mmcamcorder_sound_finalize(MMHandleType handle)
355 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
356 SOUND_INFO *info = NULL;
358 mmf_return_val_if_fail(hcamcorder, FALSE);
360 info = &(hcamcorder->snd_info);
362 pthread_mutex_lock(&(info->open_mutex));
364 if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
365 _mmcam_dbg_warn("not initialized");
366 pthread_mutex_unlock(&(info->open_mutex));
370 info->thread_run = 0;
371 pthread_cond_signal(&(info->play_cond));
374 _mmcam_dbg_log("wait for sound write thread join");
375 pthread_join(info->thread, NULL);
376 _mmcam_dbg_log("join done");
379 if (info->state == _MMCAMCORDER_SOUND_STATE_PREPARE) {
380 _mmcam_dbg_log("restore route policy [%d]", info->route_policy_backup);
382 if (info->route_policy_backup != -1) {
383 mm_sound_route_set_system_policy(info->route_policy_backup);
386 mm_sound_pcm_play_close(info->handle);
387 __cleanup_buffer(info);
390 if (info->filename) {
391 free(info->filename);
392 info->filename = NULL;
395 info->state = _MMCAMCORDER_SOUND_STATE_NONE;
396 info->route_policy_backup = -1;
398 pthread_mutex_destroy(&(info->play_mutex));
399 pthread_cond_destroy(&(info->play_cond));
401 pthread_mutex_unlock(&(info->open_mutex));
403 _mmcam_dbg_log("Done");
409 void _mmcamcorder_sound_solo_play(MMHandleType handle, const char* filepath, gboolean sync)
411 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
413 int sound_handle = 0;
415 int sound_enable = TRUE;
417 mmf_return_if_fail( filepath );
419 _mmcam_dbg_log( "START" );
421 ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
422 "capture-sound-enable", &sound_enable,
424 if (ret == MM_ERROR_NONE) {
425 if (sound_enable == FALSE) {
426 _mmcam_dbg_log("Capture sound DISABLED.");
430 _mmcam_dbg_warn("capture-sound-enable get FAILED.[%x]", ret);
433 ret = pthread_mutex_trylock(&(hcamcorder->sound_lock));
435 _mmcam_dbg_warn("g_mutex_trylock failed.[%s]", strerror(ret));
439 MMTA_ACUM_ITEM_BEGIN("CAPTURE SOUND:mm_sound_play_loud_solo_sound", FALSE);
441 ret = mm_sound_play_loud_solo_sound(filepath, VOLUME_TYPE_FIXED, __solo_sound_callback,
442 (void*)hcamcorder, &sound_handle);
443 if (ret != MM_ERROR_NONE) {
444 _mmcam_dbg_err( "Capture sound play FAILED.[%x]", ret );
447 struct timespec timeout;
450 gettimeofday( &tv, NULL );
451 timeout.tv_sec = tv.tv_sec + 2;
452 timeout.tv_nsec = tv.tv_usec * 1000;
454 _mmcam_dbg_log("Wait for signal");
456 if (!pthread_cond_timedwait(&(hcamcorder->sound_cond), &(hcamcorder->sound_lock), &timeout)) {
457 _mmcam_dbg_log("signal received.");
459 _mmcam_dbg_warn("capture sound play timeout.");
460 if (sound_handle > 0) {
461 mm_sound_stop_sound(sound_handle);
467 MMTA_ACUM_ITEM_END("CAPTURE SOUND:mm_sound_play_loud_solo_sound", FALSE);
469 pthread_mutex_unlock(&(hcamcorder->sound_lock));
471 _mmcam_dbg_log("DONE");
476 static void __solo_sound_callback(void *data)
478 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
480 mmf_return_if_fail(hcamcorder);
482 _mmcam_dbg_log("START");
484 _mmcam_dbg_log("Signal SEND");
485 pthread_cond_broadcast(&(hcamcorder->sound_cond));
487 _mmcam_dbg_log("DONE");