dev_stream.c revision 9111a0544944a9d367f5e19b15e5f03340b4a808
1/* Copyright (c) 2014 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 "audio_thread_log.h" 7#include "byte_buffer.h" 8#include "cras_fmt_conv.h" 9#include "cras_rstream.h" 10#include "dev_stream.h" 11#include "cras_audio_area.h" 12#include "cras_mix.h" 13#include "cras_rstream.h" 14#include "cras_shm.h" 15 16struct dev_stream *dev_stream_create(struct cras_rstream *stream, 17 const struct cras_audio_format *dev_fmt) 18{ 19 struct dev_stream *out; 20 struct cras_audio_format *stream_fmt = &stream->format; 21 int rc = 0; 22 unsigned int max_frames; 23 unsigned int fmt_conv_num_channels; 24 unsigned int fmt_conv_frame_bytes; 25 26 out = calloc(1, sizeof(*out)); 27 out->stream = stream; 28 29 if (stream->direction == CRAS_STREAM_OUTPUT) { 30 fmt_conv_num_channels = dev_fmt->num_channels; 31 fmt_conv_frame_bytes = cras_get_format_bytes(dev_fmt); 32 max_frames = MAX(stream->buffer_frames, 33 cras_frames_at_rate(stream_fmt->frame_rate, 34 stream->buffer_frames, 35 dev_fmt->frame_rate)); 36 rc = config_format_converter(&out->conv, 37 stream->direction, 38 stream_fmt, 39 dev_fmt, 40 max_frames); 41 } else { 42 fmt_conv_num_channels = stream->format.num_channels; 43 fmt_conv_frame_bytes = cras_get_format_bytes(&stream->format); 44 max_frames = MAX(stream->buffer_frames, 45 cras_frames_at_rate(dev_fmt->frame_rate, 46 stream->buffer_frames, 47 stream_fmt->frame_rate)); 48 rc = config_format_converter(&out->conv, 49 stream->direction, 50 dev_fmt, 51 stream_fmt, 52 max_frames); 53 } 54 if (rc) { 55 free(out); 56 return NULL; 57 } 58 59 if (out->conv) { 60 unsigned int dev_frames = 61 cras_fmt_conv_in_frames_to_out(out->conv, 62 stream->buffer_frames); 63 unsigned int buf_bytes; 64 65 out->conv_buffer_size_frames = 2 * MAX(dev_frames, 66 stream->buffer_frames); 67 buf_bytes = out->conv_buffer_size_frames * fmt_conv_frame_bytes; 68 out->conv_buffer = byte_buffer_create(buf_bytes); 69 out->conv_area = cras_audio_area_create(fmt_conv_num_channels); 70 } 71 72 return out; 73} 74 75void dev_stream_destroy(struct dev_stream *dev_stream) 76{ 77 if (dev_stream->conv) { 78 cras_audio_area_destroy(dev_stream->conv_area); 79 cras_fmt_conv_destroy(dev_stream->conv); 80 byte_buffer_destroy(dev_stream->conv_buffer); 81 } 82 free(dev_stream); 83} 84 85unsigned int dev_stream_mix(struct dev_stream *dev_stream, 86 size_t num_channels, 87 uint8_t *dst, 88 size_t *count, 89 size_t *index) 90{ 91 struct cras_audio_shm *shm; 92 int16_t *src; 93 int16_t *target = (int16_t *)dst; 94 unsigned int fr_written, fr_read; 95 int fr_in_buf; 96 unsigned int num_samples; 97 size_t frames = 0; 98 unsigned int dev_frames; 99 float mix_vol; 100 101 shm = cras_rstream_output_shm(dev_stream->stream); 102 fr_in_buf = cras_shm_get_frames(shm); 103 if (fr_in_buf <= 0) { 104 *count = 0; 105 return 0; 106 } 107 if (fr_in_buf < *count) 108 *count = fr_in_buf; 109 110 /* Stream volume scaler. */ 111 mix_vol = cras_shm_get_volume_scaler(shm); 112 113 fr_written = 0; 114 fr_read = 0; 115 while (fr_written < *count) { 116 unsigned int read_frames; 117 src = cras_shm_get_readable_frames(shm, fr_read, 118 &frames); 119 if (frames == 0) 120 break; 121 if (dev_stream->conv) { 122 read_frames = frames; 123 dev_frames = cras_fmt_conv_convert_frames( 124 dev_stream->conv, 125 (uint8_t *)src, 126 dev_stream->conv_buffer->bytes, 127 &read_frames, 128 *count - fr_written); 129 src = (int16_t *)dev_stream->conv_buffer->bytes; 130 } else { 131 dev_frames = MIN(frames, *count - fr_written); 132 read_frames = dev_frames; 133 } 134 num_samples = dev_frames * num_channels; 135 cras_mix_add(target, src, num_samples, *index, 136 cras_shm_get_mute(shm), mix_vol); 137 target += num_samples; 138 fr_written += dev_frames; 139 fr_read += read_frames; 140 } 141 142 *count = fr_written; 143 cras_shm_buffer_read(shm, fr_read); 144 audio_thread_event_log_data(atlog, AUDIO_THREAD_DEV_STREAM_MIX, 145 fr_written, fr_read, 0); 146 147 *index = *index + 1; 148 return *count; 149} 150 151/* Copy from the captured buffer to the temporary format converted buffer. */ 152static void capture_with_fmt_conv(struct dev_stream *dev_stream, 153 const uint8_t *source_samples, 154 unsigned int num_frames) 155{ 156 const struct cras_audio_format *source_format; 157 const struct cras_audio_format *dst_format; 158 uint8_t *buffer; 159 unsigned int total_read = 0; 160 unsigned int write_frames; 161 unsigned int read_frames; 162 unsigned int source_frame_bytes; 163 unsigned int dst_frame_bytes; 164 165 source_format = cras_fmt_conv_in_format(dev_stream->conv); 166 source_frame_bytes = cras_get_format_bytes(source_format); 167 dst_format = cras_fmt_conv_out_format(dev_stream->conv); 168 dst_frame_bytes = cras_get_format_bytes(dst_format); 169 170 dev_stream->conv_area->num_channels = dst_format->num_channels; 171 172 while (total_read < num_frames) { 173 buffer = buf_write_pointer_size(dev_stream->conv_buffer, 174 &write_frames); 175 write_frames /= dst_frame_bytes; 176 177 read_frames = num_frames - total_read; 178 write_frames = cras_fmt_conv_convert_frames( 179 dev_stream->conv, 180 source_samples, 181 buffer, 182 &read_frames, 183 write_frames); 184 total_read += read_frames; 185 source_samples += read_frames * source_frame_bytes; 186 buf_increment_write(dev_stream->conv_buffer, 187 write_frames * dst_frame_bytes); 188 } 189} 190 191/* Copy from the converted buffer to the stream shm. These have the same format 192 * at this point. */ 193static void capture_copy_converted_to_stream(struct dev_stream *dev_stream, 194 struct cras_rstream *rstream, 195 unsigned int dev_index) 196{ 197 struct cras_audio_shm *shm; 198 uint8_t *stream_samples; 199 uint8_t *converted_samples; 200 unsigned int num_frames; 201 unsigned int total_written = 0; 202 unsigned int write_frames; 203 unsigned int frame_bytes; 204 const struct cras_audio_format *fmt; 205 206 shm = cras_rstream_input_shm(rstream); 207 208 fmt = cras_fmt_conv_out_format(dev_stream->conv); 209 frame_bytes = cras_get_format_bytes(fmt); 210 211 stream_samples = cras_shm_get_writeable_frames( 212 shm, 213 cras_rstream_get_cb_threshold(rstream) - 214 dev_stream->mix_offset, 215 &rstream->input_audio_area->frames); 216 num_frames = MIN(rstream->input_audio_area->frames, 217 buf_queued_bytes(dev_stream->conv_buffer) / 218 frame_bytes); 219 220 audio_thread_event_log_data(atlog, AUDIO_THREAD_CONV_COPY, 221 cras_shm_frames_written(shm), 222 shm->area->write_buf_idx, 223 num_frames); 224 225 while (total_written < num_frames) { 226 converted_samples = 227 buf_read_pointer_size(dev_stream->conv_buffer, 228 &write_frames); 229 write_frames /= frame_bytes; 230 write_frames = MIN(write_frames, num_frames); 231 232 cras_audio_area_config_buf_pointers(dev_stream->conv_area, 233 fmt, 234 converted_samples); 235 cras_audio_area_config_channels(dev_stream->conv_area, fmt); 236 dev_stream->conv_area->frames = write_frames; 237 238 cras_audio_area_config_buf_pointers(rstream->input_audio_area, 239 &rstream->format, 240 stream_samples); 241 242 cras_audio_area_copy(rstream->input_audio_area, 243 dev_stream->mix_offset, 244 cras_get_format_bytes(&rstream->format), 245 dev_stream->conv_area, dev_index); 246 247 buf_increment_read(dev_stream->conv_buffer, 248 write_frames * frame_bytes); 249 total_written += write_frames; 250 dev_stream->mix_offset += write_frames; 251 } 252 253 audio_thread_event_log_data(atlog, AUDIO_THREAD_CAPTURE_WRITE, 254 rstream->stream_id, 255 total_written, 256 cras_shm_frames_written(shm)); 257} 258 259void dev_stream_capture(struct dev_stream *dev_stream, 260 const struct cras_audio_area *area, 261 unsigned int dev_index) 262{ 263 struct cras_rstream *rstream = dev_stream->stream; 264 struct cras_audio_shm *shm; 265 uint8_t *stream_samples; 266 267 /* Check if format conversion is needed. */ 268 if (dev_stream->conv) { 269 capture_with_fmt_conv(dev_stream, 270 area->channels[0].buf, 271 area->frames); 272 capture_copy_converted_to_stream(dev_stream, rstream, 273 dev_index); 274 } else { 275 /* Set up the shm area and copy to it. */ 276 shm = cras_rstream_input_shm(rstream); 277 stream_samples = cras_shm_get_writeable_frames( 278 shm, 279 cras_rstream_get_cb_threshold(rstream), 280 &rstream->input_audio_area->frames); 281 cras_audio_area_config_buf_pointers(rstream->input_audio_area, 282 &rstream->format, 283 stream_samples); 284 285 cras_audio_area_copy(rstream->input_audio_area, 286 dev_stream->mix_offset, 287 cras_get_format_bytes(&rstream->format), 288 area, dev_index); 289 dev_stream->mix_offset += area->frames; 290 audio_thread_event_log_data(atlog, AUDIO_THREAD_CAPTURE_WRITE, 291 rstream->stream_id, 292 area->frames, 293 cras_shm_frames_written(shm)); 294 } 295} 296 297int dev_stream_playback_frames(const struct dev_stream *dev_stream) 298{ 299 struct cras_audio_shm *shm; 300 int frames; 301 302 shm = cras_rstream_output_shm(dev_stream->stream); 303 304 frames = cras_shm_get_frames(shm); 305 if (frames < 0) 306 return frames; 307 308 if (!dev_stream->conv) 309 return frames; 310 311 return cras_fmt_conv_in_frames_to_out(dev_stream->conv, frames); 312} 313 314unsigned int dev_stream_capture_avail(const struct dev_stream *dev_stream) 315{ 316 struct cras_audio_shm *shm; 317 struct cras_rstream *rstream = dev_stream->stream; 318 unsigned int cb_threshold = cras_rstream_get_cb_threshold(rstream); 319 unsigned int frames_avail; 320 321 shm = cras_rstream_input_shm(rstream); 322 323 cras_shm_get_writeable_frames(shm, cb_threshold, &frames_avail); 324 325 if (!dev_stream->conv) 326 return frames_avail; 327 328 return buf_available_bytes(dev_stream->conv_buffer) / 329 cras_shm_frame_bytes(shm); 330} 331 332int dev_stream_capture_sleep_frames(struct dev_stream *dev_stream, 333 unsigned int written, 334 unsigned int *min_sleep) 335{ 336 struct cras_rstream *rstream = dev_stream->stream; 337 unsigned int str_cb_threshold = cras_rstream_get_cb_threshold(rstream); 338 unsigned int dev_cb_threshold; 339 struct cras_audio_shm *shm = cras_rstream_input_shm(rstream); 340 unsigned int str_frames, dev_frames; 341 342 if (dev_stream->conv) 343 written = cras_fmt_conv_in_frames_to_out(dev_stream->conv, 344 written); 345 cras_shm_buffer_written(shm, dev_stream->mix_offset); 346 str_frames = cras_shm_frames_written(shm); 347 348 dev_stream->mix_offset = 0; 349 350 if (dev_stream->conv) { 351 dev_frames = cras_fmt_conv_out_frames_to_in(dev_stream->conv, 352 str_frames); 353 dev_cb_threshold = cras_fmt_conv_out_frames_to_in( 354 dev_stream->conv, str_cb_threshold); 355 } else { 356 dev_frames = str_frames; 357 dev_cb_threshold = str_cb_threshold; 358 } 359 360 if (str_frames < str_cb_threshold) { 361 /* If this stream doesn't have enough data yet, skip it. */ 362 *min_sleep = MIN(*min_sleep, dev_cb_threshold - dev_frames); 363 return 0; 364 } 365 366 /* Enough data for this stream. */ 367 cras_shm_buffer_write_complete(shm); 368 *min_sleep = MIN(*min_sleep, dev_cb_threshold - 369 cras_fmt_conv_out_frames_to_in(dev_stream->conv, 370 cras_shm_frames_written(shm))); 371 372 audio_thread_event_log_data(atlog, AUDIO_THREAD_CAPTURE_POST, 373 rstream->stream_id, 374 str_cb_threshold, 375 shm->area->read_buf_idx); 376 377 /* Tell the client that samples are ready. */ 378 return cras_rstream_audio_ready(rstream, str_cb_threshold); 379} 380 381void cras_set_playback_timestamp(size_t frame_rate, 382 size_t frames, 383 struct cras_timespec *ts) 384{ 385 cras_clock_gettime(CLOCK_MONOTONIC, ts); 386 387 /* For playback, want now + samples left to be played. 388 * ts = time next written sample will be played to DAC, 389 */ 390 ts->tv_nsec += frames * 1000000000ULL / frame_rate; 391 while (ts->tv_nsec > 1000000000ULL) { 392 ts->tv_sec++; 393 ts->tv_nsec -= 1000000000ULL; 394 } 395} 396 397void cras_set_capture_timestamp(size_t frame_rate, 398 size_t frames, 399 struct cras_timespec *ts) 400{ 401 long tmp; 402 403 cras_clock_gettime(CLOCK_MONOTONIC, ts); 404 405 /* For capture, now - samples left to be read. 406 * ts = time next sample to be read was captured at ADC. 407 */ 408 tmp = frames * (1000000000L / frame_rate); 409 while (tmp > 1000000000L) { 410 tmp -= 1000000000L; 411 ts->tv_sec--; 412 } 413 if (ts->tv_nsec >= tmp) 414 ts->tv_nsec -= tmp; 415 else { 416 tmp -= ts->tv_nsec; 417 ts->tv_nsec = 1000000000L - tmp; 418 ts->tv_sec--; 419 } 420} 421 422