static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { int ret; struct stream_out *out = (struct stream_out *)stream; pthread_mutex_lock(&out->dev->lock); pthread_mutex_lock(&out->lock); if (out->standby) { ret = start_output_stream(out); if (ret != 0) { goto err; } out->standby = false; } pcm_write(out->pcm, (void *)buffer, bytes); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->dev->lock); return bytes; err: pthread_mutex_unlock(&out->lock); if (ret != 0) { usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / out_get_sample_rate(&stream->common)); } return bytes; }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { /* XXX: fake timing for audio output */ usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / out_get_sample_rate(&stream->common)); return bytes; }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { int ret; struct stream_out *out = (struct stream_out *)stream; pthread_mutex_lock(&out->dev->lock); pthread_mutex_lock(&out->lock); if (out->standby) { ret = start_output_stream(out); if (ret != 0) { pthread_mutex_unlock(&out->dev->lock); goto err; } out->standby = false; } pthread_mutex_unlock(&out->dev->lock); alsa_device_proxy* proxy = &out->proxy; const void * write_buff = buffer; int num_write_buff_bytes = bytes; const int num_device_channels = proxy_get_channel_count(proxy); /* what we told alsa */ const int num_req_channels = out->hal_channel_count; /* what we told AudioFlinger */ if (num_device_channels != num_req_channels) { /* allocate buffer */ const size_t required_conversion_buffer_size = bytes * num_device_channels / num_req_channels; if (required_conversion_buffer_size > out->conversion_buffer_size) { out->conversion_buffer_size = required_conversion_buffer_size; out->conversion_buffer = realloc(out->conversion_buffer, out->conversion_buffer_size); } /* convert data */ const audio_format_t audio_format = out_get_format(&(out->stream.common)); const unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format); num_write_buff_bytes = adjust_channels(write_buff, num_req_channels, out->conversion_buffer, num_device_channels, sample_size_in_bytes, num_write_buff_bytes); write_buff = out->conversion_buffer; } if (write_buff != NULL && num_write_buff_bytes != 0) { proxy_write(&out->proxy, write_buff, num_write_buff_bytes); } pthread_mutex_unlock(&out->lock); return bytes; err: pthread_mutex_unlock(&out->lock); if (ret != 0) { usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / out_get_sample_rate(&stream->common)); } return bytes; }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { int ret = 0; struct stream_out *out = (struct stream_out *)stream; struct audio_device *adev = out ? out->dev : NULL; if(adev == NULL) return -ENOSYS; ALOGV("%s enter",__func__); pthread_mutex_lock(&out->dev->lock); pthread_mutex_lock(&out->lock); // there is a possibility that the HD interface is open // and normal pcm stream is still active. Feed the new // interface to normal pcm stream if(adev->active_pcm) { if(adev->active_pcm != out->pcm) out->pcm = adev->active_pcm; } if ((out->standby) || (!adev->active_pcm)) { ret = start_output_stream(out); if (ret != 0) { goto err; } out->standby = false; } if(!out->pcm){ ALOGD("%s: null handle to write - device already closed",__func__); goto err; } ret = pcm_write(out->pcm, (void *)buffer, bytes); ALOGVV("%s: pcm_write returned = %d rate = %d",__func__,ret,out->pcm_config.rate); err: pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->dev->lock); if (ret != 0) { uint64_t duration_ms = ((bytes * 1000)/ (audio_stream_frame_size(&stream->common)) / (out_get_sample_rate(&stream->common))); ALOGV("%s : silence written", __func__); usleep(duration_ms * 1000); } ALOGV("%s exit",__func__); return bytes; }
static int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_devices_t devices, audio_output_flags_t flags, struct audio_config *config, struct audio_stream_out **stream_out) { struct audio_device *adev = (struct audio_device *)dev; struct stream_out *out; int ret; out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); if (!out) return -ENOMEM; out->stream.common.get_sample_rate = out_get_sample_rate; out->stream.common.set_sample_rate = out_set_sample_rate; out->stream.common.get_buffer_size = out_get_buffer_size; out->stream.common.get_channels = out_get_channels; out->stream.common.get_format = out_get_format; out->stream.common.set_format = out_set_format; out->stream.common.standby = out_standby; out->stream.common.dump = out_dump; out->stream.common.set_parameters = out_set_parameters; out->stream.common.get_parameters = out_get_parameters; out->stream.common.add_audio_effect = out_add_audio_effect; out->stream.common.remove_audio_effect = out_remove_audio_effect; out->stream.get_latency = out_get_latency; out->stream.set_volume = out_set_volume; out->stream.write = out_write; out->stream.get_render_position = out_get_render_position; out->stream.get_next_write_timestamp = out_get_next_write_timestamp; out->dev = adev; config->format = out_get_format(&out->stream.common); config->channel_mask = out_get_channels(&out->stream.common); config->sample_rate = out_get_sample_rate(&out->stream.common); out->standby = true; adev->card = -1; adev->device = -1; *stream_out = &out->stream; return 0; err_open: free(out); *stream_out = NULL; return ret; }
static uint32_t out_get_latency(const struct audio_stream_out *stream) { return (pcm_config.period_size * pcm_config.period_count * 1000) / out_get_sample_rate(&stream->common); }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { //ALOGV("out_write(bytes=%d)", bytes); ssize_t written_frames = 0; struct submix_stream_out *out = reinterpret_cast<struct submix_stream_out *>(stream); const size_t frame_size = audio_stream_frame_size(&stream->common); const size_t frames = bytes / frame_size; pthread_mutex_lock(&out->dev->lock); out->dev->output_standby = false; sp<MonoPipe> sink = out->dev->rsxSink.get(); if (sink != 0) { if (sink->isShutdown()) { sink.clear(); pthread_mutex_unlock(&out->dev->lock); // the pipe has already been shutdown, this buffer will be lost but we must // simulate timing so we don't drain the output faster than realtime usleep(frames * 1000000 / out_get_sample_rate(&stream->common)); return bytes; } } else { pthread_mutex_unlock(&out->dev->lock); ALOGE("out_write without a pipe!"); ALOG_ASSERT("out_write without a pipe!"); return 0; } pthread_mutex_unlock(&out->dev->lock); written_frames = sink->write(buffer, frames); if (written_frames < 0) { if (written_frames == (ssize_t)NEGOTIATE) { ALOGE("out_write() write to pipe returned NEGOTIATE"); pthread_mutex_lock(&out->dev->lock); sink.clear(); pthread_mutex_unlock(&out->dev->lock); written_frames = 0; return 0; } else { // write() returned UNDERRUN or WOULD_BLOCK, retry ALOGE("out_write() write to pipe returned unexpected %16lx", written_frames); written_frames = sink->write(buffer, frames); } } pthread_mutex_lock(&out->dev->lock); sink.clear(); pthread_mutex_unlock(&out->dev->lock); if (written_frames < 0) { ALOGE("out_write() failed writing to pipe with %16lx", written_frames); return 0; } else { ALOGV("out_write() wrote %lu bytes)", written_frames * frame_size); return written_frames * frame_size; } }
static int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_devices_t devices, audio_output_flags_t flags, struct audio_config *config, struct audio_stream_out **stream_out) { struct audio_device *adev = (struct audio_device *)dev; struct stream_out *out; int ret; ALOGV("%s enter card %d device %d ",__func__, adev->card, adev->device); out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); if (!out) return -ENOMEM; out->channel_mask = AUDIO_CHANNEL_OUT_STEREO; if (flags & AUDIO_OUTPUT_FLAG_DIRECT) { ALOGV("%s: USB Audio (device mode) HD",__func__); if (config->format == 0) config->format = pcm_config_HD_default.format; if (config->channel_mask == 0) config->channel_mask = AUDIO_CHANNEL_OUT_STEREO; if (config->sample_rate == 0) config->sample_rate = pcm_config_HD_default.rate; out->pcm_config.period_size = pcm_config_HD_default.period_size; out->flags |= flags; } else { ALOGV("%s: USB Audio (device mode) Stereo",__func__); if (config->format == 0) config->format = pcm_config_default.format; if (config->channel_mask == 0) config->channel_mask = AUDIO_CHANNEL_OUT_STEREO; if (config->sample_rate == 0) config->sample_rate = pcm_config_default.rate; out->pcm_config.period_size = pcm_config_default.period_size; } out->channel_mask = config->channel_mask; out->pcm_config.channels = popcount(config->channel_mask); out->pcm_config.rate = config->sample_rate; out->pcm_config.format = config->format; out->pcm_config.period_count = pcm_config_default.period_count; out->stream.common.get_sample_rate = out_get_sample_rate; out->stream.common.set_sample_rate = out_set_sample_rate; out->stream.common.get_buffer_size = out_get_buffer_size; out->stream.common.get_channels = out_get_channels; out->stream.common.get_format = out_get_format; out->stream.common.set_format = out_set_format; out->stream.common.standby = out_standby; out->stream.common.dump = out_dump; out->stream.common.set_parameters = out_set_parameters; out->stream.common.get_parameters = out_get_parameters; out->stream.common.add_audio_effect = out_add_audio_effect; out->stream.common.remove_audio_effect = out_remove_audio_effect; out->stream.get_latency = out_get_latency; out->stream.set_volume = out_set_volume; out->stream.write = out_write; out->stream.get_render_position = out_get_render_position; out->stream.get_next_write_timestamp = out_get_next_write_timestamp; out->dev = adev; config->format = out_get_format(&out->stream.common); config->channel_mask = out_get_channels(&out->stream.common); config->sample_rate = out_get_sample_rate(&out->stream.common); out->standby = true; adev->card = -1; adev->device = -1; *stream_out = &out->stream; ALOGV("%s exit",__func__); return 0; }