1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include <fcntl.h>
7 #include <stdint.h>
8 #include <sys/mman.h>
9 #include <sys/types.h>
10 #include <syslog.h>
11
12 #include "cras_audio_area.h"
13 #include "cras_config.h"
14 #include "cras_messages.h"
15 #include "cras_rclient.h"
16 #include "cras_rstream.h"
17 #include "cras_server_metrics.h"
18 #include "cras_shm.h"
19 #include "cras_types.h"
20 #include "cras_system_state.h"
21
cras_rstream_config_is_client_shm_stream(const struct cras_rstream_config * config)22 static bool cras_rstream_config_is_client_shm_stream(
23 const struct cras_rstream_config *config)
24 {
25 return config && config->client_shm_fd >= 0 &&
26 config->client_shm_size > 0;
27 }
28
29 /* Setup the shared memory area used for audio samples. config->client_shm_fd
30 * must be closed after calling this function.
31 */
setup_shm_area(struct cras_rstream * stream,struct cras_rstream_config * config)32 static inline int setup_shm_area(struct cras_rstream *stream,
33 struct cras_rstream_config *config)
34 {
35 const struct cras_audio_format *fmt = &stream->format;
36 char header_name[NAME_MAX];
37 char samples_name[NAME_MAX];
38 struct cras_shm_info header_info, samples_info;
39 uint32_t frame_bytes, used_size;
40 int rc;
41 bool client_shm_stream =
42 cras_rstream_config_is_client_shm_stream(config);
43
44 if (stream->shm) {
45 /* already setup */
46 return -EEXIST;
47 }
48
49 snprintf(header_name, sizeof(header_name),
50 "/cras-%d-stream-%08x-header", getpid(), stream->stream_id);
51
52 rc = cras_shm_info_init(header_name, cras_shm_header_size(),
53 &header_info);
54 if (rc)
55 return rc;
56
57 frame_bytes = snd_pcm_format_physical_width(fmt->format) / 8 *
58 fmt->num_channels;
59 used_size = stream->buffer_frames * frame_bytes;
60
61 if (client_shm_stream) {
62 rc = cras_shm_info_init_with_fd(config->client_shm_fd,
63 config->client_shm_size,
64 &samples_info);
65 } else {
66 snprintf(samples_name, sizeof(samples_name),
67 "/cras-%d-stream-%08x-samples", getpid(),
68 stream->stream_id);
69 rc = cras_shm_info_init(
70 samples_name,
71 cras_shm_calculate_samples_size(used_size),
72 &samples_info);
73 }
74 if (rc) {
75 cras_shm_info_cleanup(&header_info);
76 return rc;
77 }
78
79 int samples_prot = 0;
80 if (stream->direction == CRAS_STREAM_OUTPUT)
81 samples_prot = PROT_READ;
82 else
83 samples_prot = PROT_WRITE;
84
85 rc = cras_audio_shm_create(&header_info, &samples_info, samples_prot,
86 &stream->shm);
87 if (rc)
88 return rc;
89
90 cras_shm_set_frame_bytes(stream->shm, frame_bytes);
91 cras_shm_set_used_size(stream->shm, used_size);
92 if (client_shm_stream) {
93 for (int i = 0; i < 2; i++)
94 cras_shm_set_buffer_offset(stream->shm, i,
95 config->buffer_offsets[i]);
96 }
97
98 stream->audio_area =
99 cras_audio_area_create(stream->format.num_channels);
100 cras_audio_area_config_channels(stream->audio_area, &stream->format);
101
102 return 0;
103 }
104
buffer_meets_size_limit(size_t buffer_size,size_t rate)105 static inline int buffer_meets_size_limit(size_t buffer_size, size_t rate)
106 {
107 return (buffer_size < (CRAS_MAX_BUFFER_TIME_IN_S * rate)) &&
108 (buffer_size > (CRAS_MIN_BUFFER_TIME_IN_US * rate) / 1000000);
109 }
110
111 /* Verifies that the given stream parameters are valid. */
verify_rstream_parameters(const struct cras_rstream_config * config,struct cras_rstream * const * stream_out)112 static int verify_rstream_parameters(const struct cras_rstream_config *config,
113 struct cras_rstream *const *stream_out)
114 {
115 const struct cras_audio_format *format = config->format;
116
117 if (stream_out == NULL) {
118 syslog(LOG_ERR, "rstream: stream_out can't be NULL\n");
119 return -EINVAL;
120 }
121 if (format == NULL) {
122 syslog(LOG_ERR, "rstream: format can't be NULL\n");
123 return -EINVAL;
124 }
125 if (format->frame_rate < 4000 || format->frame_rate > 192000) {
126 syslog(LOG_ERR, "rstream: invalid frame_rate %zu\n",
127 format->frame_rate);
128 return -EINVAL;
129 }
130 /*
131 * Valid buffer settings:
132 * Frames in 1ms <= cb_threshold <= buffer_frames <= Frames in 10s.
133 */
134 if (!buffer_meets_size_limit(config->buffer_frames,
135 format->frame_rate)) {
136 syslog(LOG_ERR, "rstream: invalid buffer_frames %zu\n",
137 config->buffer_frames);
138 return -EINVAL;
139 }
140 if (!buffer_meets_size_limit(config->cb_threshold,
141 format->frame_rate) ||
142 config->cb_threshold > config->buffer_frames) {
143 syslog(LOG_ERR, "rstream: invalid cb_threshold %zu\n",
144 config->cb_threshold);
145 return -EINVAL;
146 }
147 if (format->num_channels < 0 || format->num_channels > CRAS_CH_MAX) {
148 syslog(LOG_ERR, "rstream: invalid num_channels %zu\n",
149 format->num_channels);
150 return -EINVAL;
151 }
152 if ((format->format != SND_PCM_FORMAT_S16_LE) &&
153 (format->format != SND_PCM_FORMAT_S32_LE) &&
154 (format->format != SND_PCM_FORMAT_U8) &&
155 (format->format != SND_PCM_FORMAT_S24_LE)) {
156 syslog(LOG_ERR, "rstream: format %d not supported\n",
157 format->format);
158 return -EINVAL;
159 }
160 if (config->direction != CRAS_STREAM_OUTPUT &&
161 config->direction != CRAS_STREAM_INPUT) {
162 syslog(LOG_ERR, "rstream: Invalid direction.\n");
163 return -EINVAL;
164 }
165 if (config->stream_type < CRAS_STREAM_TYPE_DEFAULT ||
166 config->stream_type >= CRAS_STREAM_NUM_TYPES) {
167 syslog(LOG_ERR, "rstream: Invalid stream type.\n");
168 return -EINVAL;
169 }
170 if (config->client_type < CRAS_CLIENT_TYPE_UNKNOWN ||
171 config->client_type >= CRAS_NUM_CLIENT_TYPE) {
172 syslog(LOG_ERR, "rstream: Invalid client type.\n");
173 return -EINVAL;
174 }
175 if ((config->client_shm_size > 0 && config->client_shm_fd < 0) ||
176 (config->client_shm_size == 0 && config->client_shm_fd >= 0)) {
177 syslog(LOG_ERR, "rstream: invalid client-provided shm info\n");
178 return -EINVAL;
179 }
180 if (cras_rstream_config_is_client_shm_stream(config) &&
181 (config->buffer_offsets[0] > config->client_shm_size ||
182 config->buffer_offsets[1] > config->client_shm_size)) {
183 syslog(LOG_ERR,
184 "rstream: initial buffer offsets are outside shm area\n");
185 return -EINVAL;
186 }
187
188 return 0;
189 }
190
191 /*
192 * Setting pending reply is only needed inside this module.
193 */
set_pending_reply(struct cras_rstream * stream)194 static void set_pending_reply(struct cras_rstream *stream)
195 {
196 cras_shm_set_callback_pending(stream->shm, 1);
197 }
198
199 /*
200 * Clearing pending reply is only needed inside this module.
201 */
clear_pending_reply(struct cras_rstream * stream)202 static void clear_pending_reply(struct cras_rstream *stream)
203 {
204 cras_shm_set_callback_pending(stream->shm, 0);
205 }
206
207 /*
208 * Reads one response of audio request from client.
209 * Args:
210 * stream[in]: A pointer to cras_rstream.
211 * msg[out]: A pointer to audio_message to hold the message.
212 * Returns:
213 * Number of bytes read from the socket.
214 * A negative error code if read fails or the message from client
215 * has errors.
216 */
get_audio_request_reply(const struct cras_rstream * stream,struct audio_message * msg)217 static int get_audio_request_reply(const struct cras_rstream *stream,
218 struct audio_message *msg)
219 {
220 int rc;
221
222 rc = read(stream->fd, msg, sizeof(*msg));
223 if (rc < 0)
224 return -errno;
225 if (rc == 0)
226 return rc;
227 if (msg->error < 0)
228 return msg->error;
229 return rc;
230 }
231
232 /*
233 * Reads and handles one audio message from client.
234 * Returns:
235 * Number of bytes read from the socket.
236 * A negative error code if read fails or the message from client
237 * has errors.
238 */
read_and_handle_client_message(struct cras_rstream * stream)239 static int read_and_handle_client_message(struct cras_rstream *stream)
240 {
241 struct audio_message msg;
242 int rc;
243
244 rc = get_audio_request_reply(stream, &msg);
245 if (rc <= 0) {
246 clear_pending_reply(stream);
247 return rc;
248 }
249
250 /*
251 * Got client reply that data in the input stream is captured.
252 */
253 if (stream->direction == CRAS_STREAM_INPUT &&
254 msg.id == AUDIO_MESSAGE_DATA_CAPTURED) {
255 clear_pending_reply(stream);
256 }
257
258 /*
259 * Got client reply that data for output stream is ready in shm.
260 */
261 if (stream->direction == CRAS_STREAM_OUTPUT &&
262 msg.id == AUDIO_MESSAGE_DATA_READY) {
263 clear_pending_reply(stream);
264 }
265
266 return rc;
267 }
268
269 /* Exported functions */
270
cras_rstream_create(struct cras_rstream_config * config,struct cras_rstream ** stream_out)271 int cras_rstream_create(struct cras_rstream_config *config,
272 struct cras_rstream **stream_out)
273 {
274 struct cras_rstream *stream;
275 int rc;
276
277 rc = verify_rstream_parameters(config, stream_out);
278 if (rc < 0)
279 return rc;
280
281 stream = calloc(1, sizeof(*stream));
282 if (stream == NULL)
283 return -ENOMEM;
284
285 stream->stream_id = config->stream_id;
286 stream->stream_type = config->stream_type;
287 stream->client_type = config->client_type;
288 stream->direction = config->direction;
289 stream->flags = config->flags;
290 stream->format = *config->format;
291 stream->buffer_frames = config->buffer_frames;
292 stream->cb_threshold = config->cb_threshold;
293 stream->client = config->client;
294 stream->shm = NULL;
295 stream->main_dev.dev_id = NO_DEVICE;
296 stream->main_dev.dev_ptr = NULL;
297 stream->num_missed_cb = 0;
298 stream->is_pinned = (config->dev_idx != NO_DEVICE);
299 stream->pinned_dev_idx = config->dev_idx;
300 ewma_power_init(&stream->ewma, stream->format.frame_rate);
301
302 rc = setup_shm_area(stream, config);
303 if (rc < 0) {
304 syslog(LOG_ERR, "failed to setup shm %d\n", rc);
305 free(stream);
306 return rc;
307 }
308
309 stream->fd = config->audio_fd;
310 config->audio_fd = -1;
311 stream->buf_state = buffer_share_create(stream->buffer_frames);
312 stream->apm_list =
313 (stream->direction == CRAS_STREAM_INPUT) ?
314 cras_apm_list_create(stream, config->effects) :
315 NULL;
316
317 syslog(LOG_DEBUG, "stream %x frames %zu, cb_thresh %zu",
318 config->stream_id, config->buffer_frames, config->cb_threshold);
319 *stream_out = stream;
320
321 cras_system_state_stream_added(stream->direction, stream->client_type);
322
323 clock_gettime(CLOCK_MONOTONIC_RAW, &stream->start_ts);
324
325 cras_server_metrics_stream_create(config);
326
327 return 0;
328 }
329
cras_rstream_destroy(struct cras_rstream * stream)330 void cras_rstream_destroy(struct cras_rstream *stream)
331 {
332 cras_server_metrics_stream_destroy(stream);
333 cras_system_state_stream_removed(stream->direction,
334 stream->client_type);
335 close(stream->fd);
336 cras_audio_shm_destroy(stream->shm);
337 cras_audio_area_destroy(stream->audio_area);
338 buffer_share_destroy(stream->buf_state);
339 if (stream->apm_list)
340 cras_apm_list_destroy(stream->apm_list);
341 free(stream);
342 }
343
cras_rstream_get_effects(const struct cras_rstream * stream)344 unsigned int cras_rstream_get_effects(const struct cras_rstream *stream)
345 {
346 return stream->apm_list ? cras_apm_list_get_effects(stream->apm_list) :
347 0;
348 }
349
350 struct cras_audio_format *
cras_rstream_post_processing_format(const struct cras_rstream * stream,void * dev_ptr)351 cras_rstream_post_processing_format(const struct cras_rstream *stream,
352 void *dev_ptr)
353 {
354 struct cras_apm *apm;
355
356 apm = cras_apm_list_get_active_apm((void *)stream, dev_ptr);
357 if (NULL == apm)
358 return NULL;
359 return cras_apm_list_get_format(apm);
360 }
361
cras_rstream_record_fetch_interval(struct cras_rstream * rstream,const struct timespec * now)362 void cras_rstream_record_fetch_interval(struct cras_rstream *rstream,
363 const struct timespec *now)
364 {
365 struct timespec ts;
366
367 if (rstream->last_fetch_ts.tv_sec || rstream->last_fetch_ts.tv_nsec) {
368 subtract_timespecs(now, &rstream->last_fetch_ts, &ts);
369 if (timespec_after(&ts, &rstream->longest_fetch_interval))
370 rstream->longest_fetch_interval = ts;
371 }
372 }
373
init_audio_message(struct audio_message * msg,enum CRAS_AUDIO_MESSAGE_ID id,uint32_t frames)374 static void init_audio_message(struct audio_message *msg,
375 enum CRAS_AUDIO_MESSAGE_ID id, uint32_t frames)
376 {
377 memset(msg, 0, sizeof(*msg));
378 msg->id = id;
379 msg->frames = frames;
380 }
381
cras_rstream_request_audio(struct cras_rstream * stream,const struct timespec * now)382 int cras_rstream_request_audio(struct cras_rstream *stream,
383 const struct timespec *now)
384 {
385 struct audio_message msg;
386 int rc;
387
388 /* Only request samples from output streams. */
389 if (stream->direction != CRAS_STREAM_OUTPUT)
390 return 0;
391
392 stream->last_fetch_ts = *now;
393
394 init_audio_message(&msg, AUDIO_MESSAGE_REQUEST_DATA,
395 stream->cb_threshold);
396 rc = write(stream->fd, &msg, sizeof(msg));
397 if (rc < 0)
398 return -errno;
399
400 set_pending_reply(stream);
401
402 return rc;
403 }
404
cras_rstream_audio_ready(struct cras_rstream * stream,size_t count)405 int cras_rstream_audio_ready(struct cras_rstream *stream, size_t count)
406 {
407 struct audio_message msg;
408 int rc;
409
410 cras_shm_buffer_write_complete(stream->shm);
411
412 /* Mark shm as used. */
413 if (stream_is_server_only(stream)) {
414 cras_shm_buffer_read_current(stream->shm, count);
415 return 0;
416 }
417
418 init_audio_message(&msg, AUDIO_MESSAGE_DATA_READY, count);
419 rc = write(stream->fd, &msg, sizeof(msg));
420 if (rc < 0)
421 return -errno;
422
423 set_pending_reply(stream);
424
425 return rc;
426 }
427
cras_rstream_dev_attach(struct cras_rstream * rstream,unsigned int dev_id,void * dev_ptr)428 void cras_rstream_dev_attach(struct cras_rstream *rstream, unsigned int dev_id,
429 void *dev_ptr)
430 {
431 if (buffer_share_add_id(rstream->buf_state, dev_id, dev_ptr) == 0)
432 rstream->num_attached_devs++;
433
434 /* TODO(hychao): Handle main device assignment for complicated
435 * routing case.
436 */
437 if (rstream->main_dev.dev_id == NO_DEVICE) {
438 rstream->main_dev.dev_id = dev_id;
439 rstream->main_dev.dev_ptr = dev_ptr;
440 }
441 }
442
cras_rstream_dev_detach(struct cras_rstream * rstream,unsigned int dev_id)443 void cras_rstream_dev_detach(struct cras_rstream *rstream, unsigned int dev_id)
444 {
445 if (buffer_share_rm_id(rstream->buf_state, dev_id) == 0)
446 rstream->num_attached_devs--;
447
448 if (rstream->main_dev.dev_id == dev_id) {
449 int i;
450 struct id_offset *o;
451
452 /* Choose the first device id as a main device. */
453 rstream->main_dev.dev_id = NO_DEVICE;
454 rstream->main_dev.dev_ptr = NULL;
455 for (i = 0; i < rstream->buf_state->id_sz; i++) {
456 o = &rstream->buf_state->wr_idx[i];
457 if (o->used) {
458 rstream->main_dev.dev_id = o->id;
459 rstream->main_dev.dev_ptr = o->data;
460 break;
461 }
462 }
463 }
464 }
465
cras_rstream_dev_offset_update(struct cras_rstream * rstream,unsigned int frames,unsigned int dev_id)466 void cras_rstream_dev_offset_update(struct cras_rstream *rstream,
467 unsigned int frames, unsigned int dev_id)
468 {
469 buffer_share_offset_update(rstream->buf_state, dev_id, frames);
470 }
471
cras_rstream_update_input_write_pointer(struct cras_rstream * rstream)472 void cras_rstream_update_input_write_pointer(struct cras_rstream *rstream)
473 {
474 unsigned int nwritten =
475 buffer_share_get_new_write_point(rstream->buf_state);
476
477 cras_shm_buffer_written(rstream->shm, nwritten);
478 }
479
cras_rstream_update_output_read_pointer(struct cras_rstream * rstream)480 void cras_rstream_update_output_read_pointer(struct cras_rstream *rstream)
481 {
482 size_t nfr = 0;
483 uint8_t *src;
484 unsigned int nwritten =
485 buffer_share_get_new_write_point(rstream->buf_state);
486
487 /* Retrieve the read pointer |src| start from which to calculate
488 * the EWMA power. */
489 src = cras_shm_get_readable_frames(rstream->shm, 0, &nfr);
490 ewma_power_calculate(&rstream->ewma, (int16_t *)src,
491 rstream->format.num_channels, nwritten);
492 cras_shm_buffer_read(rstream->shm, nwritten);
493 }
494
cras_rstream_dev_offset(const struct cras_rstream * rstream,unsigned int dev_id)495 unsigned int cras_rstream_dev_offset(const struct cras_rstream *rstream,
496 unsigned int dev_id)
497 {
498 return buffer_share_id_offset(rstream->buf_state, dev_id);
499 }
500
cras_rstream_update_queued_frames(struct cras_rstream * rstream)501 void cras_rstream_update_queued_frames(struct cras_rstream *rstream)
502 {
503 rstream->queued_frames =
504 MIN(cras_shm_get_frames(rstream->shm), rstream->buffer_frames);
505 }
506
cras_rstream_playable_frames(struct cras_rstream * rstream,unsigned int dev_id)507 unsigned int cras_rstream_playable_frames(struct cras_rstream *rstream,
508 unsigned int dev_id)
509 {
510 return rstream->queued_frames -
511 cras_rstream_dev_offset(rstream, dev_id);
512 }
513
cras_rstream_get_volume_scaler(struct cras_rstream * rstream)514 float cras_rstream_get_volume_scaler(struct cras_rstream *rstream)
515 {
516 return cras_shm_get_volume_scaler(rstream->shm);
517 }
518
cras_rstream_get_readable_frames(struct cras_rstream * rstream,unsigned int offset,size_t * frames)519 uint8_t *cras_rstream_get_readable_frames(struct cras_rstream *rstream,
520 unsigned int offset, size_t *frames)
521 {
522 return cras_shm_get_readable_frames(rstream->shm, offset, frames);
523 }
524
cras_rstream_get_mute(const struct cras_rstream * rstream)525 int cras_rstream_get_mute(const struct cras_rstream *rstream)
526 {
527 return cras_shm_get_mute(rstream->shm);
528 }
529
cras_rstream_is_pending_reply(const struct cras_rstream * stream)530 int cras_rstream_is_pending_reply(const struct cras_rstream *stream)
531 {
532 return cras_shm_callback_pending(stream->shm);
533 }
534
cras_rstream_flush_old_audio_messages(struct cras_rstream * stream)535 int cras_rstream_flush_old_audio_messages(struct cras_rstream *stream)
536 {
537 struct pollfd pollfd;
538 int err;
539
540 if (!stream->fd)
541 return 0;
542
543 if (stream_is_server_only(stream))
544 return 0;
545
546 pollfd.fd = stream->fd;
547 pollfd.events = POLLIN;
548
549 do {
550 err = poll(&pollfd, 1, 0);
551 if (pollfd.revents & POLLIN) {
552 err = read_and_handle_client_message(stream);
553 }
554 } while (err > 0);
555
556 if (err < 0)
557 syslog(LOG_ERR, "Error reading msg from client: rc: %d", err);
558
559 return 0;
560 }
561