linuxrec.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  2. @file
  3. @brief record demo for linux
  4. @author taozhang9
  5. @date 2016/05/27
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <fcntl.h>
  10. #include <alsa/asoundlib.h>
  11. #include <signal.h>
  12. #include <sys/stat.h>
  13. #include <pthread.h>
  14. #include "../../include/formats.h"
  15. #include "../../include/linuxrec.h"
  16. #define DBG_ON 1
  17. #if DBG_ON
  18. #define dbg printf
  19. #else
  20. #define dbg
  21. #endif
  22. /* Do not change the sequence */
  23. enum {
  24. RECORD_STATE_CREATED, /* Init */
  25. RECORD_STATE_CLOSING,
  26. RECORD_STATE_READY, /* Opened */
  27. RECORD_STATE_STOPPING, /* During Stop */
  28. RECORD_STATE_RECORDING, /* Started */
  29. };
  30. #define SAMPLE_RATE 16000
  31. #define SAMPLE_BIT_SIZE 16
  32. #define FRAME_CNT 10
  33. //#define BUF_COUNT 1
  34. #define DEF_BUFF_TIME 500000
  35. #define DEF_PERIOD_TIME 100000
  36. static int show_xrun = 1;
  37. static int start_record_internal(snd_pcm_t *pcm)
  38. {
  39. return snd_pcm_start(pcm);
  40. }
  41. static int stop_record_internal(snd_pcm_t *pcm)
  42. {
  43. return snd_pcm_drop(pcm);
  44. }
  45. static int is_stopped_internal(struct recorder *rec)
  46. {
  47. snd_pcm_state_t state;
  48. state = snd_pcm_state((snd_pcm_t *)rec->wavein_hdl);
  49. switch (state) {
  50. case SND_PCM_STATE_RUNNING:
  51. case SND_PCM_STATE_DRAINING:
  52. return 0;
  53. default: break;
  54. }
  55. return 1;
  56. }
  57. static int format_ms_to_alsa(const WAVEFORMATEX * wavfmt,
  58. snd_pcm_format_t * format)
  59. {
  60. snd_pcm_format_t tmp;
  61. tmp = snd_pcm_build_linear_format(wavfmt->wBitsPerSample,
  62. wavfmt->wBitsPerSample, wavfmt->wBitsPerSample == 8 ? 1 : 0, 0);
  63. if ( tmp == SND_PCM_FORMAT_UNKNOWN )
  64. return -EINVAL;
  65. *format = tmp;
  66. return 0;
  67. }
  68. /* set hardware and software params */
  69. static int set_hwparams(struct recorder * rec, const WAVEFORMATEX *wavfmt,
  70. unsigned int buffertime, unsigned int periodtime)
  71. {
  72. snd_pcm_hw_params_t *params;
  73. int err;
  74. unsigned int rate;
  75. snd_pcm_format_t format;
  76. snd_pcm_uframes_t size;
  77. snd_pcm_t *handle = (snd_pcm_t *)rec->wavein_hdl;
  78. rec->buffer_time = buffertime;
  79. rec->period_time = periodtime;
  80. snd_pcm_hw_params_alloca(&params);
  81. err = snd_pcm_hw_params_any(handle, params);
  82. if (err < 0) {
  83. dbg("Broken configuration for this PCM");
  84. return err;
  85. }
  86. err = snd_pcm_hw_params_set_access(handle, params,
  87. SND_PCM_ACCESS_RW_INTERLEAVED);
  88. if (err < 0) {
  89. dbg("Access type not available");
  90. return err;
  91. }
  92. err = format_ms_to_alsa(wavfmt, &format);
  93. if (err) {
  94. dbg("Invalid format");
  95. return - EINVAL;
  96. }
  97. err = snd_pcm_hw_params_set_format(handle, params, format);
  98. if (err < 0) {
  99. dbg("Sample format non available");
  100. return err;
  101. }
  102. err = snd_pcm_hw_params_set_channels(handle, params, wavfmt->nChannels);
  103. if (err < 0) {
  104. dbg("Channels count non available");
  105. return err;
  106. }
  107. rate = wavfmt->nSamplesPerSec;
  108. err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
  109. if (err < 0) {
  110. dbg("Set rate failed");
  111. return err;
  112. }
  113. if(rate != wavfmt->nSamplesPerSec) {
  114. dbg("Rate mismatch");
  115. return -EINVAL;
  116. }
  117. if (rec->buffer_time == 0 || rec->period_time == 0) {
  118. err = snd_pcm_hw_params_get_buffer_time_max(params,
  119. &rec->buffer_time, 0);
  120. assert(err >= 0);
  121. if (rec->buffer_time > 500000)
  122. rec->buffer_time = 500000;
  123. rec->period_time = rec->buffer_time / 4;
  124. }
  125. err = snd_pcm_hw_params_set_period_time_near(handle, params,
  126. &rec->period_time, 0);
  127. if (err < 0) {
  128. dbg("set period time fail");
  129. return err;
  130. }
  131. err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
  132. &rec->buffer_time, 0);
  133. if (err < 0) {
  134. dbg("set buffer time failed");
  135. return err;
  136. }
  137. err = snd_pcm_hw_params_get_period_size(params, &size, 0);
  138. if (err < 0) {
  139. dbg("get period size fail");
  140. return err;
  141. }
  142. rec->period_frames = size;
  143. err = snd_pcm_hw_params_get_buffer_size(params, &size);
  144. if (size == rec->period_frames) {
  145. dbg("Can't use period equal to buffer size (%lu == %u)",
  146. size, rec->period_frames);
  147. return -EINVAL;
  148. }
  149. rec->buffer_frames = size;
  150. rec->bits_per_frame = wavfmt->wBitsPerSample;
  151. /* set to driver */
  152. err = snd_pcm_hw_params(handle, params);
  153. if (err < 0) {
  154. dbg("Unable to install hw params:");
  155. return err;
  156. }
  157. return 0;
  158. }
  159. static int set_swparams(struct recorder * rec)
  160. {
  161. int err;
  162. snd_pcm_sw_params_t *swparams;
  163. snd_pcm_t * handle = (snd_pcm_t*)(rec->wavein_hdl);
  164. /* sw para */
  165. snd_pcm_sw_params_alloca(&swparams);
  166. err = snd_pcm_sw_params_current(handle, swparams);
  167. if (err < 0) {
  168. dbg("get current sw para fail");
  169. return err;
  170. }
  171. err = snd_pcm_sw_params_set_avail_min(handle, swparams,
  172. rec->period_frames);
  173. if (err < 0) {
  174. dbg("set avail min failed");
  175. return err;
  176. }
  177. /* set a value bigger than the buffer frames to prevent the auto start.
  178. * we use the snd_pcm_start to explicit start the pcm */
  179. err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
  180. rec->buffer_frames * 2);
  181. if (err < 0) {
  182. dbg("set start threshold fail");
  183. return err;
  184. }
  185. if ( (err = snd_pcm_sw_params(handle, swparams)) < 0) {
  186. dbg("unable to install sw params:");
  187. return err;
  188. }
  189. return 0;
  190. }
  191. static int set_params(struct recorder *rec, WAVEFORMATEX *fmt,
  192. unsigned int buffertime, unsigned int periodtime)
  193. {
  194. int err;
  195. WAVEFORMATEX defmt =
  196. {WAVE_FORMAT_PCM, 1, 16000, 32000, 2, 16, sizeof(WAVEFORMATEX)};
  197. if (fmt == NULL) {
  198. fmt = &defmt;
  199. }
  200. err = set_hwparams(rec, fmt, buffertime, periodtime);
  201. if (err)
  202. return err;
  203. err = set_swparams(rec);
  204. if (err)
  205. return err;
  206. return 0;
  207. }
  208. /*
  209. * Underrun and suspend recovery
  210. */
  211. static int xrun_recovery(snd_pcm_t *handle, int err)
  212. {
  213. if (err == -EPIPE) { /* over-run */
  214. if (show_xrun)
  215. printf("!!!!!!overrun happend!!!!!!");
  216. err = snd_pcm_prepare(handle);
  217. if (err < 0) {
  218. if (show_xrun)
  219. printf("Can't recovery from overrun,"
  220. "prepare failed: %s\n", snd_strerror(err));
  221. return err;
  222. }
  223. return 0;
  224. } else if (err == -ESTRPIPE) {
  225. while ((err = snd_pcm_resume(handle)) == -EAGAIN)
  226. usleep(200000); /* wait until the suspend flag is released */
  227. if (err < 0) {
  228. err = snd_pcm_prepare(handle);
  229. if (err < 0) {
  230. if (show_xrun)
  231. printf("Can't recovery from suspend,"
  232. "prepare failed: %s\n", snd_strerror(err));
  233. return err;
  234. }
  235. }
  236. return 0;
  237. }
  238. return err;
  239. }
  240. static ssize_t pcm_read(struct recorder *rec, size_t rcount)
  241. {
  242. ssize_t r;
  243. size_t count = rcount;
  244. char *data;
  245. snd_pcm_t *handle = (snd_pcm_t *)rec->wavein_hdl;
  246. if(!handle)
  247. return -EINVAL;
  248. data = rec->audiobuf;
  249. while (count > 0) {
  250. r = snd_pcm_readi(handle, data, count);
  251. if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
  252. snd_pcm_wait(handle, 100);
  253. } else if (r < 0) {
  254. if(xrun_recovery(handle, r) < 0) {
  255. return -1;
  256. }
  257. }
  258. if (r > 0) {
  259. count -= r;
  260. data += r * rec->bits_per_frame / 8;
  261. }
  262. }
  263. return rcount;
  264. }
  265. static void * record_thread_proc(void * para)
  266. {
  267. struct recorder * rec = (struct recorder *) para;
  268. size_t frames, bytes;
  269. sigset_t mask, oldmask;
  270. sigemptyset(&mask);
  271. sigaddset(&mask, SIGINT);
  272. sigaddset(&mask, SIGTERM);
  273. pthread_sigmask(SIG_BLOCK, &mask, &oldmask);
  274. while(1) {
  275. frames = rec->period_frames;
  276. bytes = frames * rec->bits_per_frame / 8;
  277. /* closing, exit the thread */
  278. if (rec->state == RECORD_STATE_CLOSING)
  279. break;
  280. if(rec->state < RECORD_STATE_RECORDING)
  281. usleep(100000);
  282. if (pcm_read(rec, frames) != frames) {
  283. return NULL;
  284. }
  285. if (rec->on_data_ind)
  286. rec->on_data_ind(rec->audiobuf, bytes,
  287. rec->user_cb_para);
  288. }
  289. return rec;
  290. }
  291. static int create_record_thread(void * para, pthread_t * tidp)
  292. {
  293. int err;
  294. err = pthread_create(tidp, NULL, record_thread_proc, (void *)para);
  295. if (err != 0)
  296. return err;
  297. return 0;
  298. }
  299. static void free_rec_buffer(struct recorder * rec)
  300. {
  301. if (rec->audiobuf) {
  302. free(rec->audiobuf);
  303. rec->audiobuf = NULL;
  304. }
  305. }
  306. static int prepare_rec_buffer(struct recorder * rec )
  307. {
  308. /* the read and QISRWrite is blocked, currently only support one buffer,
  309. * if overrun too much, need more buffer and another new thread
  310. * to write the audio to network */
  311. size_t sz = (rec->period_frames * rec->bits_per_frame / 8);
  312. rec->audiobuf = (char *)malloc(sz);
  313. if(!rec->audiobuf)
  314. return -ENOMEM;
  315. return 0;
  316. }
  317. static int open_recorder_internal(struct recorder * rec,
  318. record_dev_id dev, WAVEFORMATEX * fmt)
  319. {
  320. int err = 0;
  321. err = snd_pcm_open((snd_pcm_t **)&rec->wavein_hdl, dev.u.name,
  322. SND_PCM_STREAM_CAPTURE, 0);
  323. if(err < 0)
  324. goto fail;
  325. err = set_params(rec, fmt, DEF_BUFF_TIME, DEF_PERIOD_TIME);
  326. if(err)
  327. goto fail;
  328. assert(rec->bufheader == NULL);
  329. err = prepare_rec_buffer(rec);
  330. if(err)
  331. goto fail;
  332. err = create_record_thread((void*)rec,
  333. &rec->rec_thread);
  334. if(err)
  335. goto fail;
  336. return 0;
  337. fail:
  338. if(rec->wavein_hdl)
  339. snd_pcm_close((snd_pcm_t *) rec->wavein_hdl);
  340. rec->wavein_hdl = NULL;
  341. free_rec_buffer(rec);
  342. return err;
  343. }
  344. static void close_recorder_internal(struct recorder *rec)
  345. {
  346. snd_pcm_t * handle;
  347. handle = (snd_pcm_t *) rec->wavein_hdl;
  348. /* may be the thread is blocked at read, cancel it */
  349. pthread_cancel(rec->rec_thread);
  350. /* wait for the pcm thread quit first */
  351. pthread_join(rec->rec_thread, NULL);
  352. if(handle) {
  353. snd_pcm_close(handle);
  354. rec->wavein_hdl = NULL;
  355. }
  356. free_rec_buffer(rec);
  357. }
  358. /* return the count of pcm device */
  359. /* list all cards */
  360. static int get_pcm_device_cnt(snd_pcm_stream_t stream)
  361. {
  362. void **hints, **n;
  363. char *io, *filter, *name;
  364. int cnt = 0;
  365. if (snd_device_name_hint(-1, "pcm", &hints) < 0)
  366. return 0;
  367. n = hints;
  368. filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";
  369. while (*n != NULL) {
  370. io = snd_device_name_get_hint(*n, "IOID");
  371. name = snd_device_name_get_hint(*n, "NAME");
  372. if (name && (io == NULL || strcmp(io, filter) == 0))
  373. cnt ++;
  374. if (io != NULL)
  375. free(io);
  376. if (name != NULL)
  377. free(name);
  378. n++;
  379. }
  380. snd_device_name_free_hint(hints);
  381. return cnt;
  382. }
  383. /* -------------------------------------
  384. * Interfaces
  385. --------------------------------------*/
  386. /* the device id is a pcm string name in linux */
  387. record_dev_id get_default_input_dev()
  388. {
  389. record_dev_id id;
  390. id.u.name = "default";
  391. return id;
  392. }
  393. record_dev_id * list_input_device()
  394. {
  395. // TODO: unimplemented
  396. return NULL;
  397. }
  398. int get_input_dev_num()
  399. {
  400. return get_pcm_device_cnt(SND_PCM_STREAM_CAPTURE);
  401. }
  402. /* callback will be run on a new thread */
  403. int create_recorder(struct recorder ** out_rec,
  404. void (*on_data_ind)(char *data, unsigned long len, void *user_cb_para),
  405. void* user_cb_para)
  406. {
  407. struct recorder * myrec;
  408. myrec = (struct recorder *)malloc(sizeof(struct recorder));
  409. if(!myrec)
  410. return -RECORD_ERR_MEMFAIL;
  411. memset(myrec, 0, sizeof(struct recorder));
  412. myrec->on_data_ind = on_data_ind;
  413. myrec->user_cb_para = user_cb_para;
  414. myrec->state = RECORD_STATE_CREATED;
  415. *out_rec = myrec;
  416. return 0;
  417. }
  418. void destroy_recorder(struct recorder *rec)
  419. {
  420. if(!rec)
  421. return;
  422. free(rec);
  423. }
  424. int open_recorder(struct recorder * rec, record_dev_id dev, WAVEFORMATEX * fmt)
  425. {
  426. int ret = 0;
  427. if(!rec )
  428. return -RECORD_ERR_INVAL;
  429. if(rec->state >= RECORD_STATE_READY)
  430. return 0;
  431. ret = open_recorder_internal(rec, dev, fmt);
  432. if(ret == 0)
  433. rec->state = RECORD_STATE_READY;
  434. return 0;
  435. }
  436. void close_recorder(struct recorder *rec)
  437. {
  438. if(rec == NULL || rec->state < RECORD_STATE_READY)
  439. return;
  440. if(rec->state == RECORD_STATE_RECORDING)
  441. stop_record(rec);
  442. rec->state = RECORD_STATE_CLOSING;
  443. close_recorder_internal(rec);
  444. rec->state = RECORD_STATE_CREATED;
  445. }
  446. int start_record(struct recorder * rec)
  447. {
  448. int ret = 0;
  449. if(rec == NULL)
  450. return -RECORD_ERR_INVAL;
  451. if( rec->state < RECORD_STATE_READY)
  452. return -RECORD_ERR_NOT_READY;
  453. if( rec->state == RECORD_STATE_RECORDING)
  454. return 0;
  455. ret = start_record_internal((snd_pcm_t *)rec->wavein_hdl);
  456. if(ret == 0)
  457. rec->state = RECORD_STATE_RECORDING;
  458. return ret;
  459. }
  460. int stop_record(struct recorder * rec)
  461. {
  462. int ret;
  463. if(rec == NULL)
  464. return -RECORD_ERR_INVAL;
  465. if( rec->state < RECORD_STATE_RECORDING)
  466. return 0;
  467. rec->state = RECORD_STATE_STOPPING;
  468. ret = stop_record_internal((snd_pcm_t *)rec->wavein_hdl);
  469. if(ret == 0) {
  470. rec->state = RECORD_STATE_READY;
  471. }
  472. return ret;
  473. }
  474. int is_record_stopped(struct recorder *rec)
  475. {
  476. if(rec->state == RECORD_STATE_RECORDING)
  477. return 0;
  478. return is_stopped_internal(rec);
  479. }