• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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