/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include #include #include #include #include #include #include #include "audio_thread.h" #include "audio_thread_log.h" #include "buffer_share.h" #include "cras_audio_area.h" #include "cras_audio_thread_monitor.h" #include "cras_device_monitor.h" #include "cras_dsp.h" #include "cras_dsp_pipeline.h" #include "cras_fmt_conv.h" #include "cras_iodev.h" #include "cras_main_thread_log.h" #include "cras_iodev_list.h" #include "cras_mix.h" #include "cras_ramp.h" #include "cras_rstream.h" #include "cras_server_metrics.h" #include "cras_system_state.h" #include "cras_util.h" #include "dev_stream.h" #include "input_data.h" #include "utlist.h" #include "rate_estimator.h" #include "softvol_curve.h" static const float RAMP_UNMUTE_DURATION_SECS = 0.5; static const float RAMP_NEW_STREAM_DURATION_SECS = 0.01; static const float RAMP_MUTE_DURATION_SECS = 0.1; static const float RAMP_RESUME_MUTE_DURATION_SECS = 1; static const float RAMP_SWITCH_MUTE_DURATION_SECS = 0.5; static const float RAMP_VOLUME_CHANGE_DURATION_SECS = 0.1; /* * It is the lastest time for the device to wake up when it is in the normal * run state. It represents how many remaining frames in the device buffer. */ static const struct timespec dev_normal_run_wake_up_time = { 0, 1 * 1000 * 1000 /* 1 msec. */ }; /* * It is the lastest time for the device to wake up when it is in the no stream * state. It represents how many remaining frames in the device buffer. */ static const struct timespec dev_no_stream_wake_up_time = { 0, 5 * 1000 * 1000 /* 5 msec. */ }; /* * Check issu b/72496547 and commit message for the history of * rate estimator tuning. */ static const struct timespec rate_estimation_window_sz = { 5, 0 /* 5 sec. */ }; static const double rate_estimation_smooth_factor = 0.3f; static void cras_iodev_alloc_dsp(struct cras_iodev *iodev); static int default_no_stream_playback(struct cras_iodev *odev) { int rc; unsigned int hw_level, fr_to_write; unsigned int target_hw_level = odev->min_cb_level * 2; struct timespec hw_tstamp; /* The default action for no stream playback is to fill zeros. */ rc = cras_iodev_frames_queued(odev, &hw_tstamp); if (rc < 0) return rc; hw_level = rc; /* If underrun happened, handle underrun and get hw_level again. */ if (hw_level == 0) { rc = cras_iodev_output_underrun(odev, hw_level, 0); if (rc < 0) return rc; rc = cras_iodev_frames_queued(odev, &hw_tstamp); if (rc < 0) return rc; hw_level = rc; } ATLOG(atlog, AUDIO_THREAD_ODEV_DEFAULT_NO_STREAMS, odev->info.idx, hw_level, target_hw_level); fr_to_write = cras_iodev_buffer_avail(odev, hw_level); if (hw_level <= target_hw_level) { fr_to_write = MIN(target_hw_level - hw_level, fr_to_write); return cras_iodev_fill_odev_zeros(odev, fr_to_write); } return 0; } static int cras_iodev_start(struct cras_iodev *iodev) { int rc; if (!cras_iodev_is_open(iodev)) return -EPERM; if (!iodev->start) { syslog(LOG_ERR, "start called on device %s not supporting start ops", iodev->info.name); return -EINVAL; } rc = iodev->start(iodev); if (rc) return rc; iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; return 0; } /* Gets the number of frames ready for this device to play. * It is the minimum number of available samples in dev_streams. */ static unsigned int dev_playback_frames(struct cras_iodev *odev) { struct dev_stream *curr; int frames = 0; DL_FOREACH (odev->streams, curr) { int dev_frames; /* Skip stream which hasn't started running yet. */ if (!dev_stream_is_running(curr)) continue; /* If this is a single output dev stream, updates the latest * number of frames for playback. */ if (dev_stream_attached_devs(curr) == 1) dev_stream_update_frames(curr); dev_frames = dev_stream_playback_frames(curr); /* Do not handle stream error or end of draining in this * function because they should be handled in write_streams. */ if (dev_frames < 0) continue; if (!dev_frames) { if (cras_rstream_get_is_draining(curr->stream)) continue; else return 0; } if (frames == 0) frames = dev_frames; else frames = MIN(dev_frames, frames); } return frames; } /* Let device enter/leave no stream playback. * Args: * iodev[in] - The output device. * enable[in] - 1 to enter no stream playback, 0 to leave. * Returns: * 0 on success. Negative error code on failure. */ static int cras_iodev_no_stream_playback_transition(struct cras_iodev *odev, int enable) { int rc; if (odev->direction != CRAS_STREAM_OUTPUT) return -EINVAL; /* This function is for transition between normal run and * no stream run state. */ if ((odev->state != CRAS_IODEV_STATE_NORMAL_RUN) && (odev->state != CRAS_IODEV_STATE_NO_STREAM_RUN)) return -EINVAL; if (enable) { ATLOG(atlog, AUDIO_THREAD_ODEV_NO_STREAMS, odev->info.idx, 0, 0); } else { ATLOG(atlog, AUDIO_THREAD_ODEV_LEAVE_NO_STREAMS, odev->info.idx, 0, 0); } rc = odev->no_stream(odev, enable); if (rc < 0) return rc; if (enable) odev->state = CRAS_IODEV_STATE_NO_STREAM_RUN; else odev->state = CRAS_IODEV_STATE_NORMAL_RUN; return 0; } /* Determines if the output device should mute. It considers system mute, * system volume, and active node volume on the device. */ static int output_should_mute(struct cras_iodev *odev) { /* System mute has highest priority. */ if (cras_system_get_mute()) return 1; /* consider system volume and active node volume. */ return cras_iodev_is_zero_volume(odev); } int cras_iodev_is_zero_volume(const struct cras_iodev *odev) { size_t system_volume; unsigned int adjusted_node_volume; system_volume = cras_system_get_volume(); if (odev->active_node) { adjusted_node_volume = cras_iodev_adjust_node_volume( odev->active_node, system_volume); return (adjusted_node_volume == 0); } return (system_volume == 0); } /* Output device state transition diagram: * * ---------------- * -------------<-----------| S0 Closed |------<-------. * | ---------------- | * | | iodev_list enables | * | | device and adds to | * | V audio thread | iodev_list removes * | ---------------- | device from * | | S1 Open | | audio_thread and * | ---------------- | closes device * | Device with empty start | | * | ops transits into | Sample is ready | * | no stream state right V | * | after open. ---------------- | * | | S2 Normal | | * | ---------------- | * | | ^ | * | There is no stream | | Sample is ready | * | V | | * | ---------------- | * ------------->-----------| S3 No Stream |------->------ * ---------------- * * Device in open_devs can be in one of S1, S2, S3. * * cras_iodev_output_event_sample_ready change device state from S1 or S3 into * S2. */ static int cras_iodev_output_event_sample_ready(struct cras_iodev *odev) { if (odev->state == CRAS_IODEV_STATE_OPEN || odev->state == CRAS_IODEV_STATE_NO_STREAM_RUN) { /* Starts ramping up if device should not be muted. * Both mute and volume are taken into consideration. */ if (odev->ramp && !output_should_mute(odev)) { cras_iodev_start_ramp(odev, odev->initial_ramp_request); } } if (odev->state == CRAS_IODEV_STATE_OPEN) { /* S1 => S2: * If device is not started yet, and there is sample ready from * stream, fill 1 min_cb_level of zeros first and fill sample * from stream later. * Starts the device here to finish state transition. */ cras_iodev_fill_odev_zeros(odev, odev->min_cb_level); ATLOG(atlog, AUDIO_THREAD_ODEV_START, odev->info.idx, odev->min_cb_level, 0); return cras_iodev_start(odev); } else if (odev->state == CRAS_IODEV_STATE_NO_STREAM_RUN) { /* S3 => S2: * Device in no stream state get sample ready. Leave no stream * state and transit to normal run state.*/ return cras_iodev_no_stream_playback_transition(odev, 0); } else { syslog(LOG_ERR, "Device %s in state %d received sample ready event", odev->info.name, odev->state); return -EINVAL; } return 0; } /* * Exported Interface. */ /* Finds the supported sample rate that best suits the requested rate, "rrate". * Exact matches have highest priority, then integer multiples, then the default * rate for the device. */ static size_t get_best_rate(struct cras_iodev *iodev, size_t rrate) { size_t i; size_t best; if (iodev->supported_rates[0] == 0) /* No rates supported */ return 0; for (i = 0, best = 0; iodev->supported_rates[i] != 0; i++) { if (rrate == iodev->supported_rates[i] && rrate >= 44100) return rrate; if (best == 0 && (rrate % iodev->supported_rates[i] == 0 || iodev->supported_rates[i] % rrate == 0)) best = iodev->supported_rates[i]; } if (best) return best; return iodev->supported_rates[0]; } /* Finds the best match for the channel count. The following match rules * will apply in order and return the value once matched: * 1. Match the exact given channel count. * 2. Match the preferred channel count. * 3. The first channel count in the list. */ static size_t get_best_channel_count(struct cras_iodev *iodev, size_t count) { static const size_t preferred_channel_count = 2; size_t i; assert(iodev->supported_channel_counts[0] != 0); for (i = 0; iodev->supported_channel_counts[i] != 0; i++) { if (iodev->supported_channel_counts[i] == count) return count; } /* If provided count is not supported, search for preferred * channel count to which we're good at converting. */ for (i = 0; iodev->supported_channel_counts[i] != 0; i++) { if (iodev->supported_channel_counts[i] == preferred_channel_count) return preferred_channel_count; } return iodev->supported_channel_counts[0]; } /* finds the best match for the current format. If no exact match is * found, use the first. */ static snd_pcm_format_t get_best_pcm_format(struct cras_iodev *iodev, snd_pcm_format_t fmt) { size_t i; for (i = 0; iodev->supported_formats[i] != 0; i++) { if (fmt == iodev->supported_formats[i]) return fmt; } return iodev->supported_formats[0]; } /* Applies the DSP to the samples for the iodev if applicable. */ static int apply_dsp(struct cras_iodev *iodev, uint8_t *buf, size_t frames) { struct cras_dsp_context *ctx; struct pipeline *pipeline; int rc; ctx = iodev->dsp_context; if (!ctx) return 0; pipeline = cras_dsp_get_pipeline(ctx); if (!pipeline) return 0; rc = cras_dsp_pipeline_apply(pipeline, buf, iodev->format->format, frames); cras_dsp_put_pipeline(ctx); return rc; } static void cras_iodev_free_dsp(struct cras_iodev *iodev) { if (iodev->dsp_context) { cras_dsp_context_free(iodev->dsp_context); iodev->dsp_context = NULL; } } /* Modifies the number of channels in device format to the one that will be * presented to the device after any channel changes from the DSP. */ static inline void adjust_dev_channel_for_dsp(const struct cras_iodev *iodev) { struct cras_dsp_context *ctx = iodev->dsp_context; if (!ctx || !cras_dsp_get_pipeline(ctx)) return; if (iodev->direction == CRAS_STREAM_OUTPUT) iodev->format->num_channels = cras_dsp_num_output_channels(ctx); else iodev->format->num_channels = cras_dsp_num_input_channels(ctx); cras_dsp_put_pipeline(ctx); } /* Updates channel layout based on the number of channels set by a * client stream. Set a default value to format if the update call * fails. */ static void update_channel_layout(struct cras_iodev *iodev) { int rc; if (iodev->update_channel_layout == NULL) return; rc = iodev->update_channel_layout(iodev); if (rc < 0) cras_audio_format_set_default_channel_layout(iodev->format); } /* * For the specified format, removes any channels from the channel layout that * are higher than the supported number of channels. Should be used when the * number of channels of the format been reduced. */ static void trim_channel_layout(struct cras_audio_format *fmt) { int i; for (i = 0; i < CRAS_CH_MAX; i++) if (fmt->channel_layout[i] >= fmt->num_channels) fmt->channel_layout[i] = -1; } int cras_iodev_set_format(struct cras_iodev *iodev, const struct cras_audio_format *fmt) { size_t actual_rate, actual_num_channels; snd_pcm_format_t actual_format; int rc; /* Update supported formats on iodev before negotiating the final value * with what stream requested. */ if (iodev->update_supported_formats) { rc = iodev->update_supported_formats(iodev); if (rc) { syslog(LOG_ERR, "Failed to update formats"); return rc; } } /* If this device isn't already using a format, try to match the one * requested in "fmt". */ if (iodev->format == NULL) { iodev->format = malloc(sizeof(struct cras_audio_format)); if (!iodev->format) return -ENOMEM; *iodev->format = *fmt; /* Finds the actual rate of device before allocating DSP * because DSP needs to use the rate of device, not rate of * stream. */ actual_rate = get_best_rate(iodev, fmt->frame_rate); iodev->format->frame_rate = actual_rate; cras_iodev_alloc_dsp(iodev); cras_iodev_update_dsp(iodev); if (iodev->dsp_context) adjust_dev_channel_for_dsp(iodev); actual_num_channels = get_best_channel_count( iodev, iodev->format->num_channels); actual_format = get_best_pcm_format(iodev, fmt->format); if (actual_rate == 0 || actual_num_channels == 0 || actual_format == 0) { /* No compatible frame rate found. */ rc = -EINVAL; goto error; } iodev->format->format = actual_format; if (iodev->format->num_channels != actual_num_channels) { /* If the DSP for this device doesn't match, drop it. */ iodev->format->num_channels = actual_num_channels; trim_channel_layout(iodev->format); cras_iodev_free_dsp(iodev); } update_channel_layout(iodev); if (!iodev->rate_est) iodev->rate_est = rate_estimator_create( actual_rate, &rate_estimation_window_sz, rate_estimation_smooth_factor); else rate_estimator_reset_rate(iodev->rate_est, actual_rate); } return 0; error: free(iodev->format); iodev->format = NULL; return rc; } /* * Configures the external dsp module and adds it to the existing dsp pipeline. */ static void add_ext_dsp_module_to_pipeline(struct cras_iodev *iodev) { struct pipeline *pipeline; pipeline = iodev->dsp_context ? cras_dsp_get_pipeline(iodev->dsp_context) : NULL; if (!pipeline) { cras_iodev_alloc_dsp(iodev); cras_dsp_load_mock_pipeline(iodev->dsp_context, iodev->format->num_channels); pipeline = cras_dsp_get_pipeline(iodev->dsp_context); } /* dsp_context mutex locked. Now it's safe to modify dsp * pipeline resources. */ if (iodev->ext_dsp_module) iodev->ext_dsp_module->configure(iodev->ext_dsp_module, iodev->buffer_size, iodev->format->num_channels, iodev->format->frame_rate); cras_dsp_pipeline_set_sink_ext_module(pipeline, iodev->ext_dsp_module); /* Unlock dsp_context mutex. */ cras_dsp_put_pipeline(iodev->dsp_context); } /* * Releases the ext_dsp_module if it ever added to iodev's dsp pipeline. */ static void release_ext_dsp_module_from_pipeline(struct cras_iodev *iodev) { struct pipeline *pipeline; if (iodev->dsp_context == NULL) return; pipeline = cras_dsp_get_pipeline(iodev->dsp_context); if (pipeline == NULL) return; /* dsp_context mutex locked. */ cras_dsp_pipeline_set_sink_ext_module(pipeline, NULL); /* Unlock dsp_context mutex. */ cras_dsp_put_pipeline(iodev->dsp_context); } void cras_iodev_set_ext_dsp_module(struct cras_iodev *iodev, struct ext_dsp_module *ext) { iodev->ext_dsp_module = ext; if (!cras_iodev_is_open(iodev)) return; if (iodev->ext_dsp_module) add_ext_dsp_module_to_pipeline(iodev); else release_ext_dsp_module_from_pipeline(iodev); } void cras_iodev_update_dsp(struct cras_iodev *iodev) { char swap_lr_disabled = 1; if (!iodev->dsp_context) return; cras_dsp_set_variable_string(iodev->dsp_context, "dsp_name", iodev->dsp_name ?: ""); if (iodev->active_node && iodev->active_node->left_right_swapped) swap_lr_disabled = 0; cras_dsp_set_variable_boolean(iodev->dsp_context, "swap_lr_disabled", swap_lr_disabled); cras_dsp_load_pipeline(iodev->dsp_context); } int cras_iodev_dsp_set_swap_mode_for_node(struct cras_iodev *iodev, struct cras_ionode *node, int enable) { if (node->left_right_swapped == enable) return 0; /* Sets left_right_swapped property on the node. It will be used * when cras_iodev_update_dsp is called. */ node->left_right_swapped = enable; /* Possibly updates dsp if the node is active on the device and there * is dsp context. If dsp context is not created yet, * cras_iodev_update_dsp returns right away. */ if (iodev->active_node == node) cras_iodev_update_dsp(iodev); return 0; } void cras_iodev_free_format(struct cras_iodev *iodev) { free(iodev->format); iodev->format = NULL; } void cras_iodev_init_audio_area(struct cras_iodev *iodev, int num_channels) { if (iodev->area) cras_iodev_free_audio_area(iodev); iodev->area = cras_audio_area_create(num_channels); cras_audio_area_config_channels(iodev->area, iodev->format); } void cras_iodev_free_audio_area(struct cras_iodev *iodev) { if (!iodev->area) return; cras_audio_area_destroy(iodev->area); iodev->area = NULL; } void cras_iodev_free_resources(struct cras_iodev *iodev) { cras_iodev_free_dsp(iodev); rate_estimator_destroy(iodev->rate_est); if (iodev->ramp) cras_ramp_destroy(iodev->ramp); } static void cras_iodev_alloc_dsp(struct cras_iodev *iodev) { const char *purpose; if (iodev->direction == CRAS_STREAM_OUTPUT) purpose = "playback"; else purpose = "capture"; cras_iodev_free_dsp(iodev); iodev->dsp_context = cras_dsp_context_new(iodev->format->frame_rate, purpose); } void cras_iodev_fill_time_from_frames(size_t frames, size_t frame_rate, struct timespec *ts) { uint64_t to_play_usec; ts->tv_sec = 0; /* adjust sleep time to target our callback threshold */ to_play_usec = (uint64_t)frames * 1000000L / (uint64_t)frame_rate; while (to_play_usec > 1000000) { ts->tv_sec++; to_play_usec -= 1000000; } ts->tv_nsec = to_play_usec * 1000; } /* This is called when a node is plugged/unplugged */ void cras_iodev_set_node_plugged(struct cras_ionode *node, int plugged) { if (node->plugged == plugged) return; node->plugged = plugged; MAINLOG(main_log, MAIN_THREAD_NODE_PLUGGED, node->dev->info.idx, plugged, 0); if (plugged) { gettimeofday(&node->plugged_time, NULL); } else if (node == node->dev->active_node) { /* * Remove normal and pinned streams, when node unplugged. * TODO(hychao): clean this up, per crbug.com/1006646 */ cras_iodev_list_disable_dev(node->dev, true); } cras_iodev_list_notify_nodes_changed(); } void cras_iodev_add_node(struct cras_iodev *iodev, struct cras_ionode *node) { DL_APPEND(iodev->nodes, node); cras_iodev_list_notify_nodes_changed(); } void cras_iodev_rm_node(struct cras_iodev *iodev, struct cras_ionode *node) { DL_DELETE(iodev->nodes, node); cras_iodev_list_notify_nodes_changed(); } void cras_iodev_set_active_node(struct cras_iodev *iodev, struct cras_ionode *node) { iodev->active_node = node; cras_iodev_list_notify_active_node_changed(iodev->direction); } bool cras_iodev_is_aec_use_case(const struct cras_ionode *node) { if ((node->type == CRAS_NODE_TYPE_INTERNAL_SPEAKER) || (node->type == CRAS_NODE_TYPE_ECHO_REFERENCE)) return true; if (node->type == CRAS_NODE_TYPE_MIC) return (node->position == NODE_POSITION_INTERNAL) || (node->position == NODE_POSITION_FRONT); return false; } bool cras_iodev_is_on_internal_card(const struct cras_ionode *node) { if (node->type == CRAS_NODE_TYPE_INTERNAL_SPEAKER) return true; if (node->type == CRAS_NODE_TYPE_HEADPHONE) return true; if (node->type == CRAS_NODE_TYPE_MIC) return true; return false; } float cras_iodev_get_software_volume_scaler(struct cras_iodev *iodev) { unsigned int volume; volume = cras_iodev_adjust_active_node_volume(iodev, cras_system_get_volume()); if (iodev->active_node && iodev->active_node->softvol_scalers) return iodev->active_node->softvol_scalers[volume]; return softvol_get_scaler(volume); } float cras_iodev_get_software_gain_scaler(const struct cras_iodev *iodev) { if (cras_iodev_software_volume_needed(iodev)) return convert_softvol_scaler_from_dB( iodev->active_node->capture_gain); return 1.0f; } int cras_iodev_get_valid_frames(struct cras_iodev *odev, struct timespec *hw_tstamp) { int rc; if (odev->direction != CRAS_STREAM_OUTPUT) return -EINVAL; if (odev->get_valid_frames) { rc = odev->get_valid_frames(odev, hw_tstamp); if (rc < 0) return rc; if (rc < odev->min_buffer_level) return 0; return rc - odev->min_buffer_level; } else { return cras_iodev_frames_queued(odev, hw_tstamp); } } int cras_iodev_add_stream(struct cras_iodev *iodev, struct dev_stream *stream) { /* * For input stream, start stream right after adding stream. * For output stream, start stream after its first fetch such that it does not * block other existing streams. */ DL_APPEND(iodev->streams, stream); if (!iodev->buf_state) iodev->buf_state = buffer_share_create(iodev->buffer_size); if (stream->stream->direction == CRAS_STREAM_INPUT) cras_iodev_start_stream(iodev, stream); return 0; } void cras_iodev_start_stream(struct cras_iodev *iodev, struct dev_stream *stream) { unsigned int cb_threshold = dev_stream_cb_threshold(stream); if (dev_stream_is_running(stream)) return; /* * TRIGGER_ONLY streams do not want to receive data, so do not add them * to buffer_share, otherwise they'll affect other streams to receive. */ if (!(stream->stream->flags & TRIGGER_ONLY)) buffer_share_add_id(iodev->buf_state, stream->stream->stream_id, NULL); iodev->min_cb_level = MIN(iodev->min_cb_level, cb_threshold); iodev->max_cb_level = MAX(iodev->max_cb_level, cb_threshold); iodev->largest_cb_level = MAX(iodev->largest_cb_level, cb_threshold); dev_stream_set_running(stream); } struct dev_stream *cras_iodev_rm_stream(struct cras_iodev *iodev, const struct cras_rstream *rstream) { struct dev_stream *out; struct dev_stream *ret = NULL; unsigned int cb_threshold; struct timespec earliest_next_cb_ts; int set_earliest = 0; iodev->min_cb_level = iodev->buffer_size / 2; iodev->max_cb_level = 0; DL_FOREACH (iodev->streams, out) { if (out->stream == rstream) { buffer_share_rm_id(iodev->buf_state, rstream->stream_id); ret = out; DL_DELETE(iodev->streams, out); continue; } if (!dev_stream_is_running(out)) continue; cb_threshold = dev_stream_cb_threshold(out); iodev->min_cb_level = MIN(iodev->min_cb_level, cb_threshold); iodev->max_cb_level = MAX(iodev->max_cb_level, cb_threshold); if (!set_earliest) { set_earliest = 1; earliest_next_cb_ts = out->stream->next_cb_ts; } if (timespec_after(&earliest_next_cb_ts, &out->stream->next_cb_ts)) earliest_next_cb_ts = out->stream->next_cb_ts; } if (!iodev->streams) { buffer_share_destroy(iodev->buf_state); iodev->buf_state = NULL; iodev->min_cb_level = iodev->buffer_size / 2; /* Let output device transit into no stream state if it's * in normal run state now. Leave input device in normal * run state. */ if ((iodev->direction == CRAS_STREAM_OUTPUT) && (iodev->state == CRAS_IODEV_STATE_NORMAL_RUN)) cras_iodev_no_stream_playback_transition(iodev, 1); } if (!set_earliest) return ret; DL_FOREACH (iodev->streams, out) { if (!dev_stream_is_running(out)) out->stream->next_cb_ts = earliest_next_cb_ts; } return ret; } unsigned int cras_iodev_stream_offset(struct cras_iodev *iodev, struct dev_stream *stream) { return buffer_share_id_offset(iodev->buf_state, stream->stream->stream_id); } void cras_iodev_stream_written(struct cras_iodev *iodev, struct dev_stream *stream, unsigned int nwritten) { buffer_share_offset_update(iodev->buf_state, stream->stream->stream_id, nwritten); } unsigned int cras_iodev_all_streams_written(struct cras_iodev *iodev) { if (!iodev->buf_state) return 0; return buffer_share_get_new_write_point(iodev->buf_state); } unsigned int cras_iodev_max_stream_offset(const struct cras_iodev *iodev) { unsigned int max = 0; struct dev_stream *curr; DL_FOREACH (iodev->streams, curr) { /* Skip stream which hasn't started running yet. */ if (!dev_stream_is_running(curr)) continue; max = MAX(max, buffer_share_id_offset(iodev->buf_state, curr->stream->stream_id)); } return max; } int cras_iodev_open(struct cras_iodev *iodev, unsigned int cb_level, const struct cras_audio_format *fmt) { struct cras_loopback *loopback; int rc; if (iodev->pre_open_iodev_hook) iodev->pre_open_iodev_hook(); DL_FOREACH (iodev->loopbacks, loopback) { if (loopback->hook_control) loopback->hook_control(true, loopback->cb_data); } if (iodev->open_dev) { rc = iodev->open_dev(iodev); if (rc) return rc; } if (iodev->format == NULL) { rc = cras_iodev_set_format(iodev, fmt); if (rc) { iodev->close_dev(iodev); return rc; } } rc = iodev->configure_dev(iodev); if (rc < 0) { iodev->close_dev(iodev); return rc; } /* * Convert cb_level from input format to device format */ cb_level = cras_frames_at_rate(fmt->frame_rate, cb_level, iodev->format->frame_rate); /* Make sure the min_cb_level doesn't get too large. */ iodev->min_cb_level = MIN(iodev->buffer_size / 2, cb_level); iodev->max_cb_level = 0; iodev->largest_cb_level = 0; iodev->num_underruns = 0; iodev->reset_request_pending = 0; iodev->state = CRAS_IODEV_STATE_OPEN; iodev->highest_hw_level = 0; iodev->input_dsp_offset = 0; ewma_power_init(&iodev->ewma, iodev->format->frame_rate); if (iodev->direction == CRAS_STREAM_OUTPUT) { /* If device supports start ops, device can be in open state. * Otherwise, device starts running right after opening. */ if (iodev->start) { iodev->state = CRAS_IODEV_STATE_OPEN; } else { iodev->state = CRAS_IODEV_STATE_NO_STREAM_RUN; cras_iodev_fill_odev_zeros(iodev, iodev->min_cb_level); } } else { iodev->input_data = input_data_create(iodev); /* If this is the echo reference dev, its ext_dsp_module will * be set to APM reverse module. Do not override it to its * input data. */ if (iodev->ext_dsp_module == NULL) iodev->ext_dsp_module = &iodev->input_data->ext; /* Input device starts running right after opening. * No stream state is only for output device. Input device * should be in normal run state. */ iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; /* Initialize the input_streaming flag to zero.*/ iodev->input_streaming = 0; /* * The device specific gain scaler to be used in audio thread. * It's expected to stick to 1.0f if device has hardware gain * control. For alsa device, this gain value will be configured * based on UCM labels IntrinsicSensitivity. */ iodev->software_gain_scaler = cras_iodev_get_software_gain_scaler(iodev); } add_ext_dsp_module_to_pipeline(iodev); clock_gettime(CLOCK_MONOTONIC_RAW, &iodev->open_ts); return 0; } enum CRAS_IODEV_STATE cras_iodev_state(const struct cras_iodev *iodev) { return iodev->state; } int cras_iodev_close(struct cras_iodev *iodev) { struct cras_loopback *loopback; int rc; if (!cras_iodev_is_open(iodev)) return 0; if (iodev->active_node) { cras_server_metrics_device_runtime(iodev); cras_server_metrics_device_gain(iodev); cras_server_metrics_device_volume(iodev); } if (iodev->input_data) { if (iodev->ext_dsp_module == &iodev->input_data->ext) iodev->ext_dsp_module = NULL; input_data_destroy(&iodev->input_data); } rc = iodev->close_dev(iodev); if (rc) syslog(LOG_ERR, "Error closing dev %s, rc %d", iodev->info.name, rc); iodev->state = CRAS_IODEV_STATE_CLOSE; if (iodev->ramp) cras_ramp_reset(iodev->ramp); if (iodev->post_close_iodev_hook) iodev->post_close_iodev_hook(); DL_FOREACH (iodev->loopbacks, loopback) { if (loopback->hook_control) loopback->hook_control(false, loopback->cb_data); } return 0; } int cras_iodev_put_input_buffer(struct cras_iodev *iodev) { unsigned int min_frames; unsigned int dsp_frames; struct input_data *data = iodev->input_data; int rc; if (iodev->streams) min_frames = buffer_share_get_new_write_point(iodev->buf_state); else min_frames = data->area->frames; // Update the max number of frames has applied input dsp. dsp_frames = MAX(iodev->input_frames_read, iodev->input_dsp_offset); iodev->input_dsp_offset = dsp_frames - min_frames; input_data_set_all_streams_read(data, min_frames); rate_estimator_add_frames(iodev->rate_est, -min_frames); rc = iodev->put_buffer(iodev, min_frames); if (rc < 0) return rc; return min_frames; } int cras_iodev_put_output_buffer(struct cras_iodev *iodev, uint8_t *frames, unsigned int nframes, int *is_non_empty, struct cras_fmt_conv *remix_converter) { const struct cras_audio_format *fmt = iodev->format; struct cras_ramp_action ramp_action = { .type = CRAS_RAMP_ACTION_NONE, .scaler = 0.0f, .increment = 0.0f, .target = 1.0f, }; float software_volume_scaler = 1.0; int software_volume_needed = cras_iodev_software_volume_needed(iodev); int rc; struct cras_loopback *loopback; /* Calculate whether the final output was non-empty, if requested. */ if (is_non_empty) { const size_t bytes = nframes * cras_get_format_bytes(fmt); /* * Speed up checking frames are all zeros using memcmp. * frames contains all zeros if both conditions are met: * - frames[0] is 0. * - frames[i] == frames[i+1] for i in [0, 1, ..., bytes - 2]. */ *is_non_empty = bytes ? (*frames || memcmp(frames, frames + 1, bytes - 1)) : 0; } DL_FOREACH (iodev->loopbacks, loopback) { if (loopback->type == LOOPBACK_POST_MIX_PRE_DSP) loopback->hook_data(frames, nframes, iodev->format, loopback->cb_data); } ewma_power_calculate(&iodev->ewma, (int16_t *)frames, iodev->format->num_channels, nframes); rc = apply_dsp(iodev, frames, nframes); if (rc) return rc; DL_FOREACH (iodev->loopbacks, loopback) { if (loopback->type == LOOPBACK_POST_DSP) loopback->hook_data(frames, nframes, iodev->format, loopback->cb_data); } if (iodev->ramp) { ramp_action = cras_ramp_get_current_action(iodev->ramp); } /* Mute samples if adjusted volume is 0 or system is muted, plus * that this device is not ramping. */ if (output_should_mute(iodev) && ramp_action.type != CRAS_RAMP_ACTION_PARTIAL) { const unsigned int frame_bytes = cras_get_format_bytes(fmt); cras_mix_mute_buffer(frames, frame_bytes, nframes); } /* Compute scaler for software volume if needed. */ if (software_volume_needed) { software_volume_scaler = cras_iodev_get_software_volume_scaler(iodev); } if (ramp_action.type == CRAS_RAMP_ACTION_PARTIAL) { /* Scale with increment for ramp and possibly * software volume using cras_scale_buffer_increment.*/ float starting_scaler = ramp_action.scaler; float increment = ramp_action.increment; float target = ramp_action.target; if (software_volume_needed) { starting_scaler *= software_volume_scaler; increment *= software_volume_scaler; target *= software_volume_scaler; } cras_scale_buffer_increment(fmt->format, frames, nframes, starting_scaler, increment, target, fmt->num_channels); cras_ramp_update_ramped_frames(iodev->ramp, nframes); } else if (!output_should_mute(iodev) && software_volume_needed) { /* Just scale for software volume using * cras_scale_buffer. */ unsigned int nsamples = nframes * fmt->num_channels; cras_scale_buffer(fmt->format, frames, nsamples, software_volume_scaler); } if (remix_converter) cras_channel_remix_convert(remix_converter, iodev->format, frames, nframes); if (iodev->rate_est) rate_estimator_add_frames(iodev->rate_est, nframes); return iodev->put_buffer(iodev, nframes); } int cras_iodev_get_input_buffer(struct cras_iodev *iodev, unsigned int *frames) { const unsigned int frame_bytes = cras_get_format_bytes(iodev->format); struct input_data *data = iodev->input_data; int rc; uint8_t *hw_buffer; unsigned frame_requested = *frames; rc = iodev->get_buffer(iodev, &data->area, frames); if (rc < 0 || *frames == 0) return rc; if (*frames > frame_requested) { syslog(LOG_ERR, "frames returned from get_buffer is greater than " "requested: %u > %u", *frames, frame_requested); return -EINVAL; } iodev->input_frames_read = *frames; /* TODO(hychao) - This assumes interleaved audio. */ hw_buffer = data->area->channels[0].buf; /* * input_dsp_offset records the position where input dsp has applied to * last time. It's possible the requested |frames| count is smaller * than the tracked offset. That could happen when client stream uses * small buffer size and runs APM processing (which requires 10 ms * equivalent of data to process). * Only apply input dsp to the part of read buffer beyond where we've * already applied dsp. */ if (*frames > iodev->input_dsp_offset) { rc = apply_dsp(iodev, hw_buffer + iodev->input_dsp_offset * frame_bytes, *frames - iodev->input_dsp_offset); if (rc) return rc; ewma_power_calculate_area( &iodev->ewma, (int16_t *)(hw_buffer + iodev->input_dsp_offset * frame_bytes), data->area, *frames - iodev->input_dsp_offset); } if (cras_system_get_capture_mute()) cras_mix_mute_buffer(hw_buffer, frame_bytes, *frames); return rc; } int cras_iodev_get_output_buffer(struct cras_iodev *iodev, struct cras_audio_area **area, unsigned *frames) { int rc; unsigned frame_requested = *frames; rc = iodev->get_buffer(iodev, area, frames); if (*frames > frame_requested) { syslog(LOG_ERR, "frames returned from get_buffer is greater than " "requested: %u > %u", *frames, frame_requested); return -EINVAL; } return rc; } int cras_iodev_update_rate(struct cras_iodev *iodev, unsigned int level, struct timespec *level_tstamp) { /* If output underruns, reset to avoid incorrect estimated rate. */ if ((iodev->direction == CRAS_STREAM_OUTPUT) && !level) rate_estimator_reset_rate(iodev->rate_est, iodev->format->frame_rate); return rate_estimator_check(iodev->rate_est, level, level_tstamp); } int cras_iodev_reset_rate_estimator(const struct cras_iodev *iodev) { rate_estimator_reset_rate(iodev->rate_est, iodev->format->frame_rate); return 0; } double cras_iodev_get_est_rate_ratio(const struct cras_iodev *iodev) { return rate_estimator_get_rate(iodev->rate_est) / iodev->format->frame_rate; } int cras_iodev_get_dsp_delay(const struct cras_iodev *iodev) { struct cras_dsp_context *ctx; struct pipeline *pipeline; int delay; ctx = iodev->dsp_context; if (!ctx) return 0; pipeline = cras_dsp_get_pipeline(ctx); if (!pipeline) return 0; delay = cras_dsp_pipeline_get_delay(pipeline); cras_dsp_put_pipeline(ctx); return delay; } int cras_iodev_frames_queued(struct cras_iodev *iodev, struct timespec *hw_tstamp) { int rc; rc = iodev->frames_queued(iodev, hw_tstamp); if (rc < 0) return rc; if (iodev->direction == CRAS_STREAM_INPUT) { if (rc > 0) iodev->input_streaming = 1; return rc; } if (rc < iodev->min_buffer_level) return 0; return rc - iodev->min_buffer_level; } int cras_iodev_buffer_avail(struct cras_iodev *iodev, unsigned hw_level) { if (iodev->direction == CRAS_STREAM_INPUT) return hw_level; if (hw_level + iodev->min_buffer_level > iodev->buffer_size) return 0; return iodev->buffer_size - iodev->min_buffer_level - hw_level; } int cras_iodev_fill_odev_zeros(struct cras_iodev *odev, unsigned int frames) { struct cras_audio_area *area = NULL; unsigned int frame_bytes, frames_written; int rc; uint8_t *buf; if (odev->direction != CRAS_STREAM_OUTPUT) return -EINVAL; ATLOG(atlog, AUDIO_THREAD_FILL_ODEV_ZEROS, odev->info.idx, frames, 0); frame_bytes = cras_get_format_bytes(odev->format); while (frames > 0) { frames_written = frames; rc = cras_iodev_get_output_buffer(odev, &area, &frames_written); if (rc < 0) { syslog(LOG_ERR, "fill zeros fail: %d", rc); return rc; } /* This assumes consecutive channel areas. */ buf = area->channels[0].buf; memset(buf, 0, (size_t)frames_written * (size_t)frame_bytes); cras_iodev_put_output_buffer(odev, buf, frames_written, NULL, NULL); frames -= frames_written; } return 0; } int cras_iodev_output_underrun(struct cras_iodev *odev, unsigned int hw_level, unsigned int frames_written) { ATLOG(atlog, AUDIO_THREAD_UNDERRUN, odev->info.idx, hw_level, frames_written); odev->num_underruns++; cras_audio_thread_event_underrun(); if (odev->output_underrun) return odev->output_underrun(odev); else return cras_iodev_fill_odev_zeros(odev, odev->min_cb_level); } int cras_iodev_odev_should_wake(const struct cras_iodev *odev) { if (odev->direction != CRAS_STREAM_OUTPUT) return 0; if (odev->is_free_running && odev->is_free_running(odev)) return 0; /* Do not wake up for device not started yet. */ return (odev->state == CRAS_IODEV_STATE_NORMAL_RUN || odev->state == CRAS_IODEV_STATE_NO_STREAM_RUN); } unsigned int cras_iodev_default_frames_to_play_in_sleep(struct cras_iodev *odev, unsigned int *hw_level, struct timespec *hw_tstamp) { int rc = cras_iodev_frames_queued(odev, hw_tstamp); unsigned int level = (rc < 0) ? 0 : rc; unsigned int wakeup_frames; *hw_level = level; if (odev->streams) { /* * We have two cases in this scope. The first one is if there are frames * waiting to be played, audio thread will wake up when hw_level drops * to min_cb_level. This situation only happens when hardware buffer is * smaller than the client stream buffer. The second one is waking up * when hw_level drops to dev_normal_run_wake_up_time. It is a default * behavior. This wake up time is the bottom line to avoid underrun. * Normally, the audio thread does not wake up at that time because the * streams should wake it up before then. */ if (*hw_level > odev->min_cb_level && dev_playback_frames(odev)) return *hw_level - odev->min_cb_level; wakeup_frames = cras_time_to_frames( &dev_normal_run_wake_up_time, odev->format->frame_rate); if (level > wakeup_frames) return level - wakeup_frames; else return level; } /* * When this device has no stream, schedule audio thread to wake up when * hw_level drops to dev_no_stream_wake_up_time so audio thread can * fill zeros to it. We also need to consider min_cb_level in order to avoid * busyloop when device buffer size is smaller than wake up time. */ wakeup_frames = cras_time_to_frames(&dev_no_stream_wake_up_time, odev->format->frame_rate); if (level > MIN(odev->min_cb_level, wakeup_frames)) return level - MIN(odev->min_cb_level, wakeup_frames); else return 0; } unsigned int cras_iodev_frames_to_play_in_sleep(struct cras_iodev *odev, unsigned int *hw_level, struct timespec *hw_tstamp) { /* Use odev's own implementation, if not supported then fall back * to default behavior below. */ if (odev->frames_to_play_in_sleep) return odev->frames_to_play_in_sleep(odev, hw_level, hw_tstamp); else return cras_iodev_default_frames_to_play_in_sleep( odev, hw_level, hw_tstamp); } int cras_iodev_default_no_stream_playback(struct cras_iodev *odev, int enable) { if (enable) return default_no_stream_playback(odev); return 0; } int cras_iodev_prepare_output_before_write_samples(struct cras_iodev *odev) { int may_enter_normal_run; enum CRAS_IODEV_STATE state; if (odev->direction != CRAS_STREAM_OUTPUT) return -EINVAL; state = cras_iodev_state(odev); may_enter_normal_run = (state == CRAS_IODEV_STATE_OPEN || state == CRAS_IODEV_STATE_NO_STREAM_RUN); if (may_enter_normal_run && dev_playback_frames(odev)) return cras_iodev_output_event_sample_ready(odev); /* no_stream ops is called every cycle in no_stream state. */ if (state == CRAS_IODEV_STATE_NO_STREAM_RUN) return odev->no_stream(odev, 1); return 0; } unsigned int cras_iodev_get_num_underruns(const struct cras_iodev *iodev) { return iodev->num_underruns; } unsigned int cras_iodev_get_num_severe_underruns(const struct cras_iodev *iodev) { if (iodev->get_num_severe_underruns) return iodev->get_num_severe_underruns(iodev); return 0; } int cras_iodev_reset_request(struct cras_iodev *iodev) { /* Ignore requests if there is a pending request. * This function sends the request from audio thread to main * thread when audio thread finds a device is in a bad state * e.g. severe underrun. Before main thread receives the * request and resets device, audio thread might try to send * multiple requests because it finds device is still in bad * state. We should ignore requests in this cause. Otherwise, * main thread will reset device multiple times. * The flag is cleared in cras_iodev_open. * */ if (iodev->reset_request_pending) return 0; iodev->reset_request_pending = 1; return cras_device_monitor_reset_device(iodev->info.idx); } static void ramp_down_mute_callback(void *data) { struct cras_iodev *odev = (struct cras_iodev *)data; cras_device_monitor_set_device_mute_state(odev->info.idx); } /* Used in audio thread. Check the docstrings of CRAS_IODEV_RAMP_REQUEST. */ int cras_iodev_start_ramp(struct cras_iodev *odev, enum CRAS_IODEV_RAMP_REQUEST request) { cras_ramp_cb cb = NULL; void *cb_data = NULL; int rc; float from, to, duration_secs; /* Ignores request if device is closed. */ if (!cras_iodev_is_open(odev)) return 0; switch (request) { case CRAS_IODEV_RAMP_REQUEST_UP_UNMUTE: from = 0.0; to = 1.0; duration_secs = RAMP_UNMUTE_DURATION_SECS; break; case CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK: from = 0.0; to = 1.0; duration_secs = RAMP_NEW_STREAM_DURATION_SECS; break; /* Unmute -> mute. Callback to set mute state should be called after * ramping is done. */ case CRAS_IODEV_RAMP_REQUEST_DOWN_MUTE: from = 1.0; to = 0.0; duration_secs = RAMP_MUTE_DURATION_SECS; cb = ramp_down_mute_callback; cb_data = (void *)odev; break; case CRAS_IODEV_RAMP_REQUEST_RESUME_MUTE: from = 0; to = 0; duration_secs = RAMP_RESUME_MUTE_DURATION_SECS; odev->initial_ramp_request = CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; break; case CRAS_IODEV_RAMP_REQUEST_SWITCH_MUTE: from = 0; to = 0; duration_secs = RAMP_SWITCH_MUTE_DURATION_SECS; odev->initial_ramp_request = CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; break; default: return -EINVAL; } /* Starts ramping. */ rc = cras_mute_ramp_start(odev->ramp, from, to, duration_secs * odev->format->frame_rate, cb, cb_data); if (rc) return rc; /* Mute -> unmute case, unmute state should be set after ramping is * started so device can start playing with samples close to 0. */ if (request == CRAS_IODEV_RAMP_REQUEST_UP_UNMUTE) cras_device_monitor_set_device_mute_state(odev->info.idx); return 0; } int cras_iodev_start_volume_ramp(struct cras_iodev *odev, unsigned int old_volume, unsigned int new_volume) { float old_scaler, new_scaler; float from, to; if (old_volume == new_volume) return 0; if (!cras_iodev_is_open(odev)) return 0; if (!odev->format) return -EINVAL; if (odev->active_node && odev->active_node->softvol_scalers) { old_scaler = odev->active_node->softvol_scalers[old_volume]; new_scaler = odev->active_node->softvol_scalers[new_volume]; } else { old_scaler = softvol_get_scaler(old_volume); new_scaler = softvol_get_scaler(new_volume); } if (new_scaler == 0.0) { return -EINVAL; } /* We will soon set odev's volume to new_volume from old_volume. * Because we're using softvol, we were previously scaling our volume by * old_scaler. If we want to avoid a jump in volume, we need to start * our ramp so that (from * new_scaler) = old_scaler. */ from = old_scaler / new_scaler; to = 1.0; return cras_volume_ramp_start(odev->ramp, from, to, RAMP_VOLUME_CHANGE_DURATION_SECS * odev->format->frame_rate, NULL, NULL); } int cras_iodev_set_mute(struct cras_iodev *iodev) { if (!cras_iodev_is_open(iodev)) return 0; if (iodev->set_mute) iodev->set_mute(iodev); return 0; } void cras_iodev_update_highest_hw_level(struct cras_iodev *iodev, unsigned int hw_level) { /* * If the hw_level is unreasonably high and reach to the device's * buffer size, regard it as a device overrun. * In the normal status, the hw_level for should be between 1 to 2 * largest_cb_level for an output device and 0 to 1 largest_cb_level * for an input device. Therefore, larger than 3 can be considered * unreasonable. */ if (hw_level == iodev->buffer_size && iodev->largest_cb_level * 3 < iodev->buffer_size) { ATLOG(atlog, AUDIO_THREAD_DEV_OVERRUN, iodev->info.idx, hw_level, 0); /* Only log the event when the first time it happens. */ if (iodev->highest_hw_level != hw_level) cras_audio_thread_event_dev_overrun(); } iodev->highest_hw_level = MAX(iodev->highest_hw_level, hw_level); } /* * Makes an input device drop the given number of frames. * Args: * iodev - The device. * frames - How many frames will be dropped in a device. * Returns: * The number of frames have been dropped. Negative error code on failure. */ static int cras_iodev_drop_frames(struct cras_iodev *iodev, unsigned int frames) { struct timespec hw_tstamp; int i, rc; unsigned int target_frames, dropped_frames = 0; if (iodev->direction != CRAS_STREAM_INPUT) return -EINVAL; rc = cras_iodev_frames_queued(iodev, &hw_tstamp); if (rc < 0) return rc; target_frames = MIN(frames, rc); /* * Loop reading the buffer, at most twice. This is to cover when * circular buffer is at the end and returns partial of the target * frames. */ for (i = 0; (dropped_frames < target_frames) && (i < 2); i++) { frames = target_frames - dropped_frames; rc = iodev->get_buffer(iodev, &iodev->input_data->area, &frames); if (rc < 0) return rc; rc = iodev->put_buffer(iodev, frames); if (rc < 0) return rc; dropped_frames += frames; /* * Tell rate estimator that some frames have been dropped to * avoid calculating the wrong rate. */ rate_estimator_add_frames(iodev->rate_est, -frames); } ATLOG(atlog, AUDIO_THREAD_DEV_DROP_FRAMES, iodev->info.idx, dropped_frames, 0); return frames; } int cras_iodev_drop_frames_by_time(struct cras_iodev *iodev, struct timespec ts) { int frames_to_set; double est_rate; int rc; est_rate = iodev->format->frame_rate * cras_iodev_get_est_rate_ratio(iodev); frames_to_set = cras_time_to_frames(&ts, est_rate); rc = cras_iodev_drop_frames(iodev, frames_to_set); return rc; } bool cras_iodev_support_noise_cancellation(const struct cras_iodev *iodev) { if (iodev->direction != CRAS_STREAM_INPUT) return false; if (iodev->support_noise_cancellation) return !!iodev->support_noise_cancellation(iodev); return false; }