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