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