blob: 40f89e5e8beb3cbde4becf366a0f1d7a656b04c1 [file] [log] [blame]
b.liu1c1c7212023-12-22 16:35:27 +08001#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <fcntl.h>
5#include <errno.h>
b.liu9e8584b2024-11-06 19:21:28 +08006#include <cutils/str_parms.h>
b.liu1c1c7212023-12-22 16:35:27 +08007
8#include "mbtk_log.h"
9#include "mbtk_audio_internal.h"
luojianfee10dc2024-07-25 11:34:35 +080010#include "audio_if_audio_hw_mrvl.h"
b.liu1c1c7212023-12-22 16:35:27 +080011
12#define LOCK_FILE "/var/run/mbtk_audio.lock"
13#define AUDIO_DEBUG 0
14
15#define AUDIO_LOG(fmt, args ...) \
16 do{ \
17 if(AUDIO_DEBUG) {LOGD(fmt, ##args);} \
18 } while(0)
19
20extern void* audio_hal_install(void);
21extern void audio_hal_uninstall(void);
22extern void configure_vcm(unsigned int data[]);
23
24static audio_inter_info_t *audio_info = NULL;
25static pthread_t recorder_thread_play;
b.liud0ea5642024-10-17 10:28:51 +080026static mbtk_audio_pa_switch_func audio_pa_switch_func = NULL;
27static mbtk_audio_volume_set_func audio_volume_set_func = NULL;
28static int audio_pcm_write_count = 0;
b.liu1c1c7212023-12-22 16:35:27 +080029
30static int lock_get() {
b.liub3b923a2024-06-06 15:15:49 +080031 int fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0666);
b.liu1c1c7212023-12-22 16:35:27 +080032 if (fd == -1) {
33 LOGE("Open(%s) fail:%d", LOCK_FILE, errno);
34 return -1;
35 }
36 // 尝试对文件进行加锁
37 struct flock fl;
38 fl.l_type = F_WRLCK;
39 fl.l_whence = SEEK_SET;
40 fl.l_start = 0;
41 fl.l_len = 1;
42 int ret = fcntl(fd, F_SETLK, &fl);
43 if (ret == -1) {
44 LOGE("Another instance is running, exiting...");
45 close(fd);
46 return -1;
47 }
48 close(fd);
49 LOGD("Get file lock.");
50 return 0;
51}
52
53static int lock_free() {
b.liub3b923a2024-06-06 15:15:49 +080054 int fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0666);
b.liu1c1c7212023-12-22 16:35:27 +080055 if (fd == -1) {
56 LOGE("Open(%s) fail:%d", LOCK_FILE, errno);
57 return -1;
58 }
59 // 释放文件锁
60 struct flock fl;
61 fl.l_type = F_UNLCK;
62 fl.l_whence = SEEK_SET;
63 fl.l_start = 0;
64 fl.l_len = 1;
65 int ret = fcntl(fd, F_SETLK, &fl);
66 if (ret == -1) {
67 LOGE("Another instance is running, exiting...");
68 close(fd);
69 return -1;
70 }
71
72 LOGD("Free file lock.");
73 return 0;
74}
75
76static void audio_recorder_thread(void *arg)
77{
b.liu9e8584b2024-11-06 19:21:28 +080078 int len, frames = 0;
b.liu1c1c7212023-12-22 16:35:27 +080079 char buff[MBTK_PCM_WB_BUF_SIZE];
80
81 audio_info->info.recorder.state = AUDIO_RECORDER_STATE_RUNNING;
82 pthread_mutex_init(&audio_info->info.recorder.mutex, NULL);
83 pthread_cond_init(&audio_info->info.recorder.cond, NULL);
84
85 while (TRUE) {
86 /* Playback loop */
87 pthread_mutex_lock(&audio_info->info.recorder.mutex);
88 if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_STOP) {
89 LOGD("Stop recorder...");
90 pthread_mutex_unlock(&audio_info->info.recorder.mutex);
91 break;
92 } else if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
93 pthread_cond_wait(&audio_info->info.recorder.cond, &audio_info->info.recorder.mutex);
94 pthread_mutex_unlock(&audio_info->info.recorder.mutex);
95 continue;
96 } else {
97 pthread_mutex_unlock(&audio_info->info.recorder.mutex);
98 }
99
100 //record the needed format stream from the device.
101 //only read pcm stream, no send command.
102 len = audio_info->info.recorder.stream_in->read(audio_info->info.recorder.stream_in, buff,
103 audio_info->playback_size);
104 if (len <= 0) {
105 LOGE("%s: error reading!", __FUNCTION__);
106 goto thread_end;
107 }
108
109 AUDIO_LOG("Recorder data : len - %d", len);
110
111 if(audio_info->info.recorder.recorder_cb) {
112 audio_info->info.recorder.recorder_cb(buff, len);
113 }
114
115 LOGD("%s: No.%d frame playback.", __FUNCTION__, ++frames);
116 }
117
118
119thread_end:
120 pthread_mutex_destroy(&audio_info->info.recorder.mutex);
121 pthread_cond_destroy(&audio_info->info.recorder.cond);
122
123 audio_info->info.recorder.stream_in->common.standby(&audio_info->info.recorder.stream_in->common);
124 audio_info->audio_ahw_dev_ubus->close_input_stream(audio_info->audio_ahw_dev_ubus, audio_info->info.recorder.stream_in);
125 VCMDeinit();//close the fd of audiostub_ctl when exit the thread.
126 audio_info->info.recorder.stream_in = NULL;
127 LOGD("%s: finished pcm playback.", __FUNCTION__);
128
129 // Notify audio recorder data end.
130 if(audio_info->info.recorder.recorder_cb) {
131 audio_info->info.recorder.recorder_cb(NULL, 0);
132 }
133 return;
134}
135
136
137static int config_parameters(mbtk_audio_direction_enum direction, mbtk_audio_sample_rate_enum NBWB)
138{
139 unsigned int srcdst, priority, dest;
140 char kvpair[128];
141 struct str_parms *param = NULL;
142 int data[5];
143 const char *key = NULL;
144 bool update_vcm = false;
145
146 srcdst = 1;/* 0-None, 1-Near end, 2-Far end, 3-Both ends */
147 priority = 1;/* 0-Do not combine(override), 1-Combine */
148 dest = 1;/* 0-Near codec, 1-Near Vocoder */
149
150 if(direction == MBTK_AUDIO_DIRECTION_OUTPUT){//output
151 if(NBWB == MBTK_AUDIO_SAMPLE_RATE_8000)
152 audio_info->playback_size = MBTK_PCM_NB_BUF_SIZE;
153 else
154 audio_info->playback_size = MBTK_PCM_WB_BUF_SIZE;
155
156 LOGD("config playback parameters.");
157 }
158 else if(direction == MBTK_AUDIO_DIRECTION_INPUT){//input
159 if(NBWB == MBTK_AUDIO_SAMPLE_RATE_8000)
160 audio_info->playback_size = MBTK_PCM_NB_BUF_SIZE;
161 else
162 audio_info->playback_size = MBTK_PCM_WB_BUF_SIZE;
163
164 LOGD("config record parameters.");
165 }
166
167 memset(kvpair, 0x00, sizeof(kvpair));
168 sprintf(kvpair, "%s=%d;%s=%d;%s=%d;%s=%d;%s=%d", VCM_CONFIG_DIRECTION, direction,
169 VCM_CONFIG_TYPE, NBWB, VCM_CONFIG_SRC_DST, srcdst,
170 VCM_CONFIG_PRIORITY, priority, VCM_CONFIG_DEST, dest);
171
172 LOGD("%s: config information kvpair is %s.\n", __FUNCTION__, kvpair);
173
174 //extract the parameter and config from string
175 param = str_parms_create_str(kvpair);
176 if (!param) {
177 LOGE("%s: param create str is null!", __FUNCTION__);
178 return -1;
179 }
180
181 //set vcm configurations
182 key = VCM_CONFIG_DIRECTION;
183 if (str_parms_get_int(param, key, &data[0]) == 0) {
184 update_vcm = true;
185 str_parms_del(param, key);
186 }
187 key = VCM_CONFIG_TYPE;
188 if (str_parms_get_int(param, key, &data[1]) == 0) {
189 update_vcm = true;
190 str_parms_del(param, key);
191 }
192 key = VCM_CONFIG_SRC_DST;
193 if (str_parms_get_int(param, key, &data[2]) == 0) {
194 update_vcm = true;
195 str_parms_del(param, key);
196 }
197 key = VCM_CONFIG_PRIORITY;
198 if (str_parms_get_int(param, key, &data[3]) == 0) {
199 update_vcm = true;
200 str_parms_del(param, key);
201 }
202 key = VCM_CONFIG_DEST;
203 if (str_parms_get_int(param, key, &data[4]) == 0) {
204 update_vcm = true;
205 str_parms_del(param, key);
206 }
207
208 //printf("Direction is %d, Type is %d, Src_Dst is %d, Priority is %d, Dest is %d. \n",data[0], data[1], data[2], data[3], data[4]);
209
210 if (update_vcm) {
b.liu9e8584b2024-11-06 19:21:28 +0800211 configure_vcm((unsigned int*)data); /*TODO check if all inputs got all values successfully*/
b.liu1c1c7212023-12-22 16:35:27 +0800212 }
213
214 return 0;
215}
216
217int mbtk_audio_pcm_init()
218{
219 //mbtk_log_init("radio", "MBTK_AUDIO");
220 // Audio is running...
221 if(lock_get()) {
222 return -1;
223 }
224
225 if(audio_info) {
226 return 0;
227 }
228
229 audio_info = (audio_inter_info_t*)malloc(sizeof(audio_inter_info_t));
230 if(audio_info == NULL) {
231 LOGE("malloc() fail:%d", errno);
232 return -1;
233 }
234 memset(audio_info, 0x00, sizeof(audio_inter_info_t));
235
236 // Set default audio parameter.
237 audio_info->channel = 1;
238 audio_info->sample_rate = MBTK_AUDIO_SAMPLE_RATE_8000;
239 audio_info->playback_size = MBTK_PCM_NB_BUF_SIZE;
240
241 audio_info->audio_ahw_dev_ubus = audio_hal_install();
242 if (audio_info->audio_ahw_dev_ubus == NULL) {
243 LOGE("audio_hal_install() failed!");
244 goto init_fail;
245 }
246 return 0;
247init_fail:
248 free(audio_info);
249 audio_info = NULL;
250 return -1;
251}
252
b.liud0ea5642024-10-17 10:28:51 +0800253void mbtk_audio_pa_func_set(mbtk_audio_pa_switch_func pa_switch_func)
254{
255 audio_pa_switch_func = pa_switch_func;
256}
257
258void mbtk_audio_volume_set_func_set(mbtk_audio_volume_set_func volume_set_func)
259{
260 audio_volume_set_func = volume_set_func;
261}
262
b.liu1c1c7212023-12-22 16:35:27 +0800263int mbtk_audio_pcm_sample_rate_set(mbtk_audio_sample_rate_enum sample_rate)
264{
265 if(!audio_info) {
266 LOGE("Not inited.");
267 return -1;
268 }
269
270 audio_info->sample_rate = sample_rate;
271
272 return 0;
273}
274
275int mbtk_audio_pcm_play_start()
276{
277 if(!audio_info) {
278 LOGE("Not inited.");
279 return -1;
280 }
281
282 if(!audio_info->audio_ahw_dev_ubus) {
283 LOGE("audio_info->audio_ahw_dev_ubus is NULL.");
284 return -1;
285 }
286
287 config_parameters(MBTK_AUDIO_DIRECTION_OUTPUT, audio_info->sample_rate);
288
289 int rc = audio_info->audio_ahw_dev_ubus->open_output_stream(audio_info->audio_ahw_dev_ubus, 0,
290 audio_info->audio_ahw_dev_ubus->get_supported_devices(audio_info->audio_ahw_dev_ubus),
291 AUDIO_OUTPUT_FLAG_DIRECT, NULL, &(audio_info->info.play.stream_out), 0);
292 if (rc < 0) {
293 LOGE("Open output device fail:%d", rc);
294 goto play_start_fail;
295 }
296
297 audio_info->direction = MBTK_AUDIO_DIRECTION_OUTPUT;
298 audio_info->info.play.buff_remain_len = 0;
b.liud0ea5642024-10-17 10:28:51 +0800299 audio_pcm_write_count = 0;
b.liu1c1c7212023-12-22 16:35:27 +0800300
301 return 0;
302play_start_fail:
303
304 return -1;
305}
306
307int mbtk_audio_pcm_play_data_send(const void* data,uint32 data_len)
308{
309 UNUSED(data);
310 UNUSED(data_len);
311
312 if(!audio_info) {
313 LOGE("Not inited.");
314 return -1;
315 }
316
317 if(!audio_info->info.play.stream_out) {
318 LOGE("Output device not open.");
319 return -1;
320 }
321
322 uint32 index = 0;
323 // There are remaining data from the previous package。
324 if(audio_info->info.play.buff_remain_len > 0) {
325 // Too less for one package.
326 if(data_len + audio_info->info.play.buff_remain_len < audio_info->playback_size) {
327 AUDIO_LOG("Save remain data : len - %d", data_len);
328 memcpy(audio_info->info.play.buff_remain + audio_info->info.play.buff_remain_len, data, data_len);
329 audio_info->info.play.buff_remain_len += data_len;
330 return data_len;
331 } else {
332 AUDIO_LOG("Write remain data : %d + %d", audio_info->info.play.buff_remain_len, audio_info->playback_size - audio_info->info.play.buff_remain_len);
333 memcpy(audio_info->info.play.buff_remain + audio_info->info.play.buff_remain_len, data, audio_info->playback_size - audio_info->info.play.buff_remain_len);
334
335 int rc = audio_info->info.play.stream_out->write(audio_info->info.play.stream_out, audio_info->info.play.buff_remain, audio_info->playback_size);
336 if (rc < 0) {
337 LOGE("%s: error writing (child).", __FUNCTION__);
338 goto send_fail;
339 } else if (rc < (signed int)audio_info->playback_size) {
340 LOGW("%s: wrote less than buffer size, rc=%d.", __FUNCTION__, rc);
341 index += rc;
342 goto send_fail;
343 }
344
b.liud0ea5642024-10-17 10:28:51 +0800345 if(audio_pcm_write_count < 3) {
346 audio_pcm_write_count++;
347 if(audio_pcm_write_count == 3) {
348 // Set audio volume.
349 if(audio_volume_set_func) {
350 audio_volume_set_func();
351 }
352
353 // Open PA
354 if(audio_pa_switch_func) {
355 audio_pa_switch_func(TRUE);
356 }
357 }
358 }
359
b.liu1c1c7212023-12-22 16:35:27 +0800360 index += (audio_info->playback_size - audio_info->info.play.buff_remain_len);
361 audio_info->info.play.buff_remain_len = 0;
362 }
363 }
364
365 while(data_len - index >= audio_info->playback_size) {
366 AUDIO_LOG("Package : %d -> %d", index, index + audio_info->playback_size - 1);
367 int rc = audio_info->info.play.stream_out->write(audio_info->info.play.stream_out, (const char*)data + index, audio_info->playback_size);
368 if (rc < 0) {
369 LOGE("%s: error writing (child).", __FUNCTION__);
370 goto send_fail;
371 } else if (rc < (signed int)audio_info->playback_size) {
372 LOGW("%s: wrote less than buffer size, rc=%d.", __FUNCTION__, rc);
373 goto send_fail;
374 }
375
376 index += rc;
377 }
378
379 // Last package.( less then audio_info->playback_size)
380 // Save to buffer audio_info->play_buff_remain
381 if(data_len - index > 0) {
382 AUDIO_LOG("Save remain data : len - %d", data_len - index);
383 memcpy(audio_info->info.play.buff_remain, data + index, data_len - index);
384 audio_info->info.play.buff_remain_len = data_len - index;
385 }
386
387 return data_len;
388send_fail:
389 return -1;
390}
391
392int mbtk_audio_pcm_play_stop()
393{
394 if(!audio_info) {
395 LOGE("Not inited.");
396 return -1;
397 }
398
399 if(!audio_info->info.play.stream_out) {
400 LOGE("Output device not open.");
401 return -1;
402 }
403
404 // Write last package.
405 if(audio_info->info.play.buff_remain_len > 0) {
406 char buf[MBTK_PCM_WB_BUF_SIZE];
407 memset(buf, 0x00, sizeof(buf));
408 memcpy(buf, audio_info->info.play.buff_remain, audio_info->info.play.buff_remain_len);
409
410 LOGD("len %d is smaller than needed %d, so fill the buffer with 0.", audio_info->info.play.buff_remain_len, audio_info->playback_size);
411
412 int rc = audio_info->info.play.stream_out->write(audio_info->info.play.stream_out, buf, audio_info->playback_size);
413 if (rc < 0) {
414 LOGE("%s: error writing (child).", __FUNCTION__);
415 //goto send_fail;
416 } else if (rc < (signed int)audio_info->playback_size) {
417 LOGW("%s: wrote less than buffer size, rc=%d.", __FUNCTION__, rc);
418 //goto send_fail;
419 }
420 audio_info->info.play.buff_remain_len = 0;
421 }
422
b.liud0ea5642024-10-17 10:28:51 +0800423 // Close PA
424 if(audio_pa_switch_func) {
425 audio_pa_switch_func(FALSE);
426 }
427
428 vcm_playback_drain(80);//wait for drain the AP audiostub queue.
b.liu1c1c7212023-12-22 16:35:27 +0800429 usleep(80000);//delay 80ms until DSP play out its buffered data.
430 audio_info->info.play.stream_out->common.standby(&(audio_info->info.play.stream_out->common));
431 audio_info->audio_ahw_dev_ubus->close_output_stream(audio_info->audio_ahw_dev_ubus, audio_info->info.play.stream_out);
432
433 audio_info->info.play.stream_out = NULL;
434 return 0;
435}
436
437
438int mbtk_audio_pcm_recorder_start(mbtk_recorder_callback_func recorder_cb)
439{
440 if(!audio_info) {
441 LOGE("Not inited.");
442 return -1;
443 }
444
445 if(!audio_info->audio_ahw_dev_ubus) {
446 LOGE("audio_info->audio_ahw_dev_ubus is NULL.");
447 return -1;
448 }
449
450 if(audio_info->info.recorder.state != AUDIO_RECORDER_STATE_STOP) {
451 LOGW("Audio is recorder...");
452 return -1;
453 }
454
455 config_parameters(MBTK_AUDIO_DIRECTION_INPUT, audio_info->sample_rate);
456
457 VCMInit();
458
459 int rc = audio_info->audio_ahw_dev_ubus->open_input_stream(audio_info->audio_ahw_dev_ubus, 0,
460 audio_info->audio_ahw_dev_ubus->get_supported_devices(audio_info->audio_ahw_dev_ubus),
461 NULL, &(audio_info->info.recorder.stream_in), 0, 0, AUDIO_SOURCE_VOICE_CALL);
462 if (rc < 0) {
463 LOGE("Open input device fail:%d", rc);
464 goto recorder_start_fail;
465 }
466
467 audio_info->direction = MBTK_AUDIO_DIRECTION_INPUT;
468 audio_info->info.recorder.recorder_cb = recorder_cb;
469
470 pthread_attr_t thread_attr;
471 pthread_attr_init(&thread_attr);
472 if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
473 {
474 LOGE("pthread_attr_setdetachstate() fail.");
475 return -1;
476 }
477
478 if (pthread_create(&recorder_thread_play, NULL, (void *)&audio_recorder_thread, NULL) < 0) {
479 LOGE("%s: error creating thread_recorder!", __FUNCTION__);
480 return -1;
481 }
482
483 return 0;
484recorder_start_fail:
485
486 return -1;
487}
488
489int mbtk_audio_pcm_recorder_pause()
490{
491 int result = 0;
492 pthread_mutex_lock(&audio_info->info.recorder.mutex);
493 if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_RUNNING) {
494 audio_info->info.recorder.state = AUDIO_RECORDER_STATE_PAUSE;
495 } else {
496 result = -1;
497 LOGW("Audio state : %d", audio_info->info.recorder.state);
498 }
499 pthread_mutex_unlock(&audio_info->info.recorder.mutex);
500 return result;
501}
502
503int mbtk_audio_pcm_recorder_resume()
504{
505 int result = 0;
506 pthread_mutex_lock(&audio_info->info.recorder.mutex);
507 if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
508 audio_info->info.recorder.state = AUDIO_RECORDER_STATE_RUNNING;
509 pthread_cond_signal(&audio_info->info.recorder.cond);
510 } else {
511 result = -1;
512 LOGW("Audio state : %d", audio_info->info.recorder.state);
513 }
514 pthread_mutex_unlock(&audio_info->info.recorder.mutex);
515 return result;
516}
517
518
519int mbtk_audio_pcm_recorder_stop()
520{
521 int result = 0;
522 pthread_mutex_lock(&audio_info->info.recorder.mutex);
523 if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE || audio_info->info.recorder.state == AUDIO_RECORDER_STATE_RUNNING) {
524 if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
525 pthread_cond_signal(&audio_info->info.recorder.cond);
526 }
527 audio_info->info.recorder.state = AUDIO_RECORDER_STATE_STOP;
528 pthread_mutex_unlock(&audio_info->info.recorder.mutex);
529
530 LOGD("Waitting recorder thread exit...");
531 if (pthread_join(recorder_thread_play, NULL)) {
532 LOGE("error join thread_recorder!");
533 // abort();
534 }
535 LOGD("Recorder thread exit success.");
536 } else {
537 pthread_mutex_unlock(&audio_info->info.recorder.mutex);
538 result = -1;
539 LOGW("Audio state : %d", audio_info->info.recorder.state);
540 }
541
542 return result;
543}
544
545int mbtk_audio_pcm_deinit()
546{
547 if(!audio_info) {
548 LOGE("Not inited.");
549 return -1;
550 }
551
552 audio_hal_uninstall();
553
554 if(lock_free()) {
555 return -1;
556 }
557
558 free(audio_info);
559 audio_info = NULL;
560 return 0;
561}
562