static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t bytes) { struct stream_in *in = (struct stream_in *)stream; struct audio_device *adev = in->dev; int i, ret = -1; ALOGV("%s enter",__func__); pthread_mutex_lock(&in->lock); if (in->standby) { pthread_mutex_lock(&adev->lock); ret = start_input_stream(in); pthread_mutex_unlock(&adev->lock); if (ret != 0) { goto exit; } in->standby = false; } if (in->pcm) { ret = pcm_read(in->pcm, buffer, bytes); } ALOGV("in_read returned %d bytes ret = %d",bytes,ret); exit: pthread_mutex_unlock(&in->lock); if (ret != 0) { in_standby(&in->stream.common); uint64_t duration_ms = ((bytes * 1000)/ (audio_stream_frame_size(&in->stream.common)) / (in_get_sample_rate(&in->stream.common))); ALOGV("%s : silence read - read failed", __func__); usleep(duration_ms * 1000); } ALOGV("%s exit",__func__); return bytes; }
/* TODO mutex stuff here (see out_write) */ static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes) { size_t num_read_buff_bytes = 0; void * read_buff = buffer; void * out_buff = buffer; int ret = 0; struct stream_in * in = (struct stream_in *)stream; lock_input_stream(in); if (in->standby) { pthread_mutex_lock(&in->dev->lock); ret = start_input_stream(in); pthread_mutex_unlock(&in->dev->lock); if (ret != 0) { goto err; } in->standby = false; } alsa_device_profile * profile = in->profile; /* * OK, we need to figure out how much data to read to be able to output the requested * number of bytes in the HAL format (16-bit, stereo). */ num_read_buff_bytes = bytes; int num_device_channels = proxy_get_channel_count(&in->proxy); /* what we told Alsa */ int num_req_channels = in->hal_channel_count; /* what we told AudioFlinger */ if (num_device_channels != num_req_channels) { num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels; } /* Setup/Realloc the conversion buffer (if necessary). */ if (num_read_buff_bytes != bytes) { if (num_read_buff_bytes > in->conversion_buffer_size) { /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats (and do these conversions themselves) */ in->conversion_buffer_size = num_read_buff_bytes; in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size); } read_buff = in->conversion_buffer; } ret = proxy_read(&in->proxy, read_buff, num_read_buff_bytes); if (ret == 0) { if (num_device_channels != num_req_channels) { // ALOGV("chans dev:%d req:%d", num_device_channels, num_req_channels); out_buff = buffer; /* Num Channels conversion */ if (num_device_channels != num_req_channels) { audio_format_t audio_format = in_get_format(&(in->stream.common)); unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format); num_read_buff_bytes = adjust_channels(read_buff, num_device_channels, out_buff, num_req_channels, sample_size_in_bytes, num_read_buff_bytes); } } /* no need to acquire in->dev->lock to read mic_muted here as we don't change its state */ if (num_read_buff_bytes > 0 && in->dev->mic_muted) memset(buffer, 0, num_read_buff_bytes); } else { num_read_buff_bytes = 0; // reset the value after headset is unplugged } err: pthread_mutex_unlock(&in->lock); return num_read_buff_bytes; }