status_t AudioStreamOut::open( audio_io_handle_t handle, audio_devices_t devices, struct audio_config *config, const char *address) { audio_stream_out_t *outStream; int status = hwDev()->open_output_stream( hwDev(), handle, devices, flags, config, &outStream, address); ALOGV("AudioStreamOut::open(), HAL open_output_stream returned " " %p, sampleRate %d, Format %#x, " "channelMask %#x, status %d", outStream, config->sample_rate, config->format, config->channel_mask, status); if (status == NO_ERROR) { stream = outStream; mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format); ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm); mHalFrameSize = audio_stream_out_frame_size(stream); } return status; }
static size_t out_get_buffer_size(const struct audio_stream *stream) { const struct stream_out* out = (const struct stream_out*)stream; size_t buffer_size = proxy_get_period_size(&out->proxy) * audio_stream_out_frame_size(&(out->stream)); return buffer_size; }
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; }