blob: 82aadb5dffdf1e6a0918371525a025b9a1c6cbb8 [file] [log] [blame]
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "r_submix"
Jean-Michel Trivi35a2c162012-09-17 10:13:26 -070018//#define LOG_NDEBUG 0
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070019
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070023#include <stdlib.h>
Stewart Milesc049a0a2014-05-01 09:03:27 -070024#include <sys/param.h>
25#include <sys/time.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070026
27#include <cutils/log.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070028#include <cutils/properties.h>
Stewart Milesc049a0a2014-05-01 09:03:27 -070029#include <cutils/str_parms.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070030
Stewart Milesc049a0a2014-05-01 09:03:27 -070031#include <hardware/audio.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070032#include <hardware/hardware.h>
33#include <system/audio.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070034
Stewart Milesc049a0a2014-05-01 09:03:27 -070035#include <media/AudioParameter.h>
36#include <media/AudioBufferProvider.h>
Jean-Michel Trivieec87702012-09-17 09:59:42 -070037#include <media/nbaio/MonoPipe.h>
38#include <media/nbaio/MonoPipeReader.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070039
Jean-Michel Trivid4413032012-09-30 11:08:06 -070040#include <utils/String8.h>
Jean-Michel Trivid4413032012-09-30 11:08:06 -070041
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070042extern "C" {
43
44namespace android {
45
Stewart Milesc049a0a2014-05-01 09:03:27 -070046// Set to 1 to enable extremely verbose logging in this module.
47#define SUBMIX_VERBOSE_LOGGING 0
48#if SUBMIX_VERBOSE_LOGGING
49#define SUBMIX_ALOGV(...) ALOGV(__VA_ARGS__)
50#define SUBMIX_ALOGE(...) ALOGE(__VA_ARGS__)
51#else
52#define SUBMIX_ALOGV(...)
53#define SUBMIX_ALOGE(...)
54#endif // SUBMIX_VERBOSE_LOGGING
55
Stewart Miles568e66f2014-05-01 09:03:27 -070056// Size of the pipe's buffer in frames.
Jean-Michel Trivieec87702012-09-17 09:59:42 -070057#define MAX_PIPE_DEPTH_IN_FRAMES (1024*8)
Stewart Miles568e66f2014-05-01 09:03:27 -070058// Maximum number of frames users of the input and output stream should buffer.
59#define PERIOD_SIZE_IN_FRAMES 1024
Jean-Michel Trivieec87702012-09-17 09:59:42 -070060// The duration of MAX_READ_ATTEMPTS * READ_ATTEMPT_SLEEP_MS must be stricly inferior to
61// the duration of a record buffer at the current record sample rate (of the device, not of
62// the recording itself). Here we have:
63// 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -070064#define MAX_READ_ATTEMPTS 3
Jean-Michel Trivieec87702012-09-17 09:59:42 -070065#define READ_ATTEMPT_SLEEP_MS 5 // 5ms between two read attempts when pipe is empty
Stewart Miles568e66f2014-05-01 09:03:27 -070066#define DEFAULT_SAMPLE_RATE_HZ 48000 // default sample rate
67// See NBAIO_Format frameworks/av/include/media/nbaio/NBAIO.h.
68#define DEFAULT_FORMAT AUDIO_FORMAT_PCM_16_BIT
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070069
Stewart Miles70726842014-05-01 09:03:27 -070070// Set *result_variable_ptr to true if value_to_find is present in the array array_to_search,
71// otherwise set *result_variable_ptr to false.
72#define SUBMIX_VALUE_IN_SET(value_to_find, array_to_search, result_variable_ptr) \
73 { \
74 size_t i; \
75 *(result_variable_ptr) = false; \
76 for (i = 0; i < sizeof(array_to_search) / sizeof((array_to_search)[0]); i++) { \
77 if ((value_to_find) == (array_to_search)[i]) { \
78 *(result_variable_ptr) = true; \
79 break; \
80 } \
81 } \
82 }
83
Stewart Miles568e66f2014-05-01 09:03:27 -070084// Configuration of the submix pipe.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070085struct submix_config {
Stewart Miles70726842014-05-01 09:03:27 -070086 // Channel mask field in this data structure is set to either input_channel_mask or
87 // output_channel_mask depending upon the last stream to be opened on this device.
88 struct audio_config common;
89 // Input stream and output stream channel masks. This is required since input and output
90 // channel bitfields are not equivalent.
91 audio_channel_mask_t input_channel_mask;
92 audio_channel_mask_t output_channel_mask;
Stewart Miles568e66f2014-05-01 09:03:27 -070093 size_t period_size; // Size of the audio pipe is period_size * period_count in frames.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070094};
95
96struct submix_audio_device {
97 struct audio_hw_device device;
Jean-Michel Trivieec87702012-09-17 09:59:42 -070098 bool input_standby;
Stewart Miles70726842014-05-01 09:03:27 -070099 bool output_standby;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700100 submix_config config;
101 // Pipe variables: they handle the ring buffer that "pipes" audio:
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700102 // - from the submix virtual audio output == what needs to be played
103 // remotely, seen as an output for AudioFlinger
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700104 // - to the virtual audio source == what is captured by the component
105 // which "records" the submix / virtual audio source, and handles it as needed.
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700106 // A usecase example is one where the component capturing the audio is then sending it over
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700107 // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a
108 // TV with Wifi Display capabilities), or to a wireless audio player.
Stewart Miles568e66f2014-05-01 09:03:27 -0700109 sp<MonoPipe> rsxSink;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700110 sp<MonoPipeReader> rsxSource;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700111
Stewart Miles568e66f2014-05-01 09:03:27 -0700112 // Device lock, also used to protect access to submix_audio_device from the input and output
113 // streams.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700114 pthread_mutex_t lock;
115};
116
117struct submix_stream_out {
118 struct audio_stream_out stream;
119 struct submix_audio_device *dev;
120};
121
122struct submix_stream_in {
123 struct audio_stream_in stream;
124 struct submix_audio_device *dev;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700125 bool output_standby; // output standby state as seen from record thread
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700126
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700127 // wall clock when recording starts
128 struct timespec record_start_time;
129 // how many frames have been requested to be read
130 int64_t read_counter_frames;
131};
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700132
Stewart Miles70726842014-05-01 09:03:27 -0700133// Determine whether the specified sample rate is supported by the submix module.
134static bool sample_rate_supported(const uint32_t sample_rate)
135{
136 // Set of sample rates supported by Format_from_SR_C() frameworks/av/media/libnbaio/NAIO.cpp.
137 static const unsigned int supported_sample_rates[] = {
138 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
139 };
140 bool return_value;
141 SUBMIX_VALUE_IN_SET(sample_rate, supported_sample_rates, &return_value);
142 return return_value;
143}
144
145// Determine whether the specified sample rate is supported, if it is return the specified sample
146// rate, otherwise return the default sample rate for the submix module.
147static uint32_t get_supported_sample_rate(uint32_t sample_rate)
148{
149 return sample_rate_supported(sample_rate) ? sample_rate : DEFAULT_SAMPLE_RATE_HZ;
150}
151
152// Determine whether the specified channel in mask is supported by the submix module.
153static bool channel_in_mask_supported(const audio_channel_mask_t channel_in_mask)
154{
155 // Set of channel in masks supported by Format_from_SR_C()
156 // frameworks/av/media/libnbaio/NAIO.cpp.
157 static const audio_channel_mask_t supported_channel_in_masks[] = {
158 AUDIO_CHANNEL_IN_MONO, AUDIO_CHANNEL_IN_STEREO,
159 };
160 bool return_value;
161 SUBMIX_VALUE_IN_SET(channel_in_mask, supported_channel_in_masks, &return_value);
162 return return_value;
163}
164
165// Determine whether the specified channel in mask is supported, if it is return the specified
166// channel in mask, otherwise return the default channel in mask for the submix module.
167static audio_channel_mask_t get_supported_channel_in_mask(
168 const audio_channel_mask_t channel_in_mask)
169{
170 return channel_in_mask_supported(channel_in_mask) ? channel_in_mask :
171 static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_IN_STEREO);
172}
173
174// Determine whether the specified channel out mask is supported by the submix module.
175static bool channel_out_mask_supported(const audio_channel_mask_t channel_out_mask)
176{
177 // Set of channel out masks supported by Format_from_SR_C()
178 // frameworks/av/media/libnbaio/NAIO.cpp.
179 static const audio_channel_mask_t supported_channel_out_masks[] = {
180 AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO,
181 };
182 bool return_value;
183 SUBMIX_VALUE_IN_SET(channel_out_mask, supported_channel_out_masks, &return_value);
184 return return_value;
185}
186
187// Determine whether the specified channel out mask is supported, if it is return the specified
188// channel out mask, otherwise return the default channel out mask for the submix module.
189static audio_channel_mask_t get_supported_channel_out_mask(
190 const audio_channel_mask_t channel_out_mask)
191{
192 return channel_out_mask_supported(channel_out_mask) ? channel_out_mask :
193 static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_OUT_STEREO);
194}
195
Stewart Milesf645c5e2014-05-01 09:03:27 -0700196// Get a pointer to submix_stream_out given an audio_stream_out that is embedded within the
197// structure.
198static struct submix_stream_out * audio_stream_out_get_submix_stream_out(
199 struct audio_stream_out * const stream)
200{
201 ALOG_ASSERT(stream);
202 return reinterpret_cast<struct submix_stream_out *>(reinterpret_cast<uint8_t *>(stream) -
203 offsetof(struct submix_stream_out, stream));
204}
205
206// Get a pointer to submix_stream_out given an audio_stream that is embedded within the structure.
207static struct submix_stream_out * audio_stream_get_submix_stream_out(
208 struct audio_stream * const stream)
209{
210 ALOG_ASSERT(stream);
211 return audio_stream_out_get_submix_stream_out(
212 reinterpret_cast<struct audio_stream_out *>(stream));
213}
214
215// Get a pointer to submix_stream_in given an audio_stream_in that is embedded within the
216// structure.
217static struct submix_stream_in * audio_stream_in_get_submix_stream_in(
218 struct audio_stream_in * const stream)
219{
220 ALOG_ASSERT(stream);
221 return reinterpret_cast<struct submix_stream_in *>(reinterpret_cast<uint8_t *>(stream) -
222 offsetof(struct submix_stream_in, stream));
223}
224
225// Get a pointer to submix_stream_in given an audio_stream that is embedded within the structure.
226static struct submix_stream_in * audio_stream_get_submix_stream_in(
227 struct audio_stream * const stream)
228{
229 ALOG_ASSERT(stream);
230 return audio_stream_in_get_submix_stream_in(
231 reinterpret_cast<struct audio_stream_in *>(stream));
232}
233
234// Get a pointer to submix_audio_device given a pointer to an audio_device that is embedded within
235// the structure.
236static struct submix_audio_device * audio_hw_device_get_submix_audio_device(
237 struct audio_hw_device *device)
238{
239 ALOG_ASSERT(device);
240 return reinterpret_cast<struct submix_audio_device *>(reinterpret_cast<uint8_t *>(device) -
241 offsetof(struct submix_audio_device, device));
242}
243
Stewart Miles568e66f2014-05-01 09:03:27 -0700244// Get the number of channels referenced by the specified channel_mask. The channel_mask can
245// reference either input or output channels.
246uint32_t get_channel_count_from_mask(const audio_channel_mask_t channel_mask) {
247 if (audio_is_input_channel(channel_mask)) {
248 return popcount(channel_mask & AUDIO_CHANNEL_IN_ALL);
249 } else if (audio_is_output_channel(channel_mask)) {
250 return popcount(channel_mask & AUDIO_CHANNEL_OUT_ALL);
251 }
252 ALOGE("get_channel_count(): No channels specified in channel mask %x", channel_mask);
253 return 0;
254}
255
Stewart Miles70726842014-05-01 09:03:27 -0700256// Convert a input channel mask to output channel mask where a mapping is available, returns 0
257// otherwise.
258static audio_channel_mask_t audio_channel_in_mask_to_out(
259 const audio_channel_mask_t channel_in_mask)
260{
261 switch (channel_in_mask) {
262 case AUDIO_CHANNEL_IN_MONO:
263 return AUDIO_CHANNEL_OUT_MONO;
264 case AUDIO_CHANNEL_IN_STEREO:
265 return AUDIO_CHANNEL_OUT_STEREO;
266 default:
267 return 0;
268 }
269}
270
271// Compare an audio_config with input channel mask and an audio_config with output channel mask
272// returning false if they do *not* match, true otherwise.
273static bool audio_config_compare(const audio_config * const input_config,
274 const audio_config * const output_config)
275{
276 audio_channel_mask_t channel_mask = audio_channel_in_mask_to_out(input_config->channel_mask);
277 if (channel_mask != output_config->channel_mask) {
278 ALOGE("audio_config_compare() channel mask mismatch %x (%x) vs. %x",
279 channel_mask, input_config->channel_mask, output_config->channel_mask);
280 return false;
281 }
282 if (input_config->sample_rate != output_config->sample_rate) {
283 ALOGE("audio_config_compare() sample rate mismatch %ul vs. %ul",
284 input_config->sample_rate, output_config->sample_rate);
285 return false;
286 }
287 if (input_config->format != output_config->format) {
288 ALOGE("audio_config_compare() format mismatch %x vs. %x",
289 input_config->format, output_config->format);
290 return false;
291 }
292 // This purposely ignores offload_info as it's not required for the submix device.
293 return true;
294}
295
296// Sanitize the user specified audio config for a submix input / output stream.
297static void submix_sanitize_config(struct audio_config * const config, const bool is_input_format)
298{
299 config->channel_mask = is_input_format ? get_supported_channel_in_mask(config->channel_mask) :
300 get_supported_channel_out_mask(config->channel_mask);
301 config->sample_rate = get_supported_sample_rate(config->sample_rate);
302 config->format = DEFAULT_FORMAT;
303}
304
305// Verify a submix input or output stream can be opened.
306static bool submix_open_validate(const struct submix_audio_device * const rsxadev,
307 pthread_mutex_t * const lock,
308 const struct audio_config * const config,
309 const bool opening_input)
310{
311 bool pipe_open;
312 audio_config pipe_config;
313
314 // Query the device for the current audio config and whether input and output streams are open.
315 pthread_mutex_lock(lock);
316 pipe_open = rsxadev->rsxSink.get() != NULL || rsxadev->rsxSource.get() != NULL;
317 memcpy(&pipe_config, &rsxadev->config.common, sizeof(pipe_config));
318 pthread_mutex_unlock(lock);
319
320 // If the pipe is open, verify the existing audio config the pipe matches the user
321 // specified config.
322 if (pipe_open) {
323 const audio_config * const input_config = opening_input ? config : &pipe_config;
324 const audio_config * const output_config = opening_input ? &pipe_config : config;
325 // Get the channel mask of the open device.
326 pipe_config.channel_mask =
327 opening_input ? rsxadev->config.output_channel_mask :
328 rsxadev->config.input_channel_mask;
329 if (!audio_config_compare(input_config, output_config)) {
330 ALOGE("submix_open_validate(): Unsupported format.");
331 return -EINVAL;
332 }
333 }
334 return true;
335}
336
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700337/* audio HAL functions */
338
339static uint32_t out_get_sample_rate(const struct audio_stream *stream)
340{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700341 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
342 const_cast<struct audio_stream *>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700343 const uint32_t out_rate = out->dev->config.common.sample_rate;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700344 SUBMIX_ALOGV("out_get_sample_rate() returns %u", out_rate);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700345 return out_rate;
346}
347
348static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
349{
Stewart Miles70726842014-05-01 09:03:27 -0700350 if (!sample_rate_supported(rate)) {
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700351 ALOGE("out_set_sample_rate(rate=%u) rate unsupported", rate);
352 return -ENOSYS;
353 }
Stewart Milesf645c5e2014-05-01 09:03:27 -0700354 struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream);
Stewart Milesc049a0a2014-05-01 09:03:27 -0700355 SUBMIX_ALOGV("out_set_sample_rate(rate=%u)", rate);
Stewart Miles70726842014-05-01 09:03:27 -0700356 out->dev->config.common.sample_rate = rate;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700357 return 0;
358}
359
360static size_t out_get_buffer_size(const struct audio_stream *stream)
361{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700362 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
363 const_cast<struct audio_stream *>(stream));
Stewart Miles568e66f2014-05-01 09:03:27 -0700364 const struct submix_config * const config = &out->dev->config;
365 const size_t buffer_size = config->period_size * audio_stream_frame_size(stream);
366 SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames",
Stewart Miles70726842014-05-01 09:03:27 -0700367 buffer_size, config->period_size);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700368 return buffer_size;
369}
370
371static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
372{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700373 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
374 const_cast<struct audio_stream *>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700375 uint32_t channel_mask = out->dev->config.output_channel_mask;
Stewart Miles568e66f2014-05-01 09:03:27 -0700376 SUBMIX_ALOGV("out_get_channels() returns %08x", channel_mask);
377 return channel_mask;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700378}
379
380static audio_format_t out_get_format(const struct audio_stream *stream)
381{
Stewart Miles568e66f2014-05-01 09:03:27 -0700382 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
383 const_cast<struct audio_stream *>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700384 const audio_format_t format = out->dev->config.common.format;
Stewart Miles568e66f2014-05-01 09:03:27 -0700385 SUBMIX_ALOGV("out_get_format() returns %x", format);
386 return format;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700387}
388
389static int out_set_format(struct audio_stream *stream, audio_format_t format)
390{
Stewart Miles568e66f2014-05-01 09:03:27 -0700391 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700392 if (format != out->dev->config.common.format) {
Stewart Milesc049a0a2014-05-01 09:03:27 -0700393 ALOGE("out_set_format(format=%x) format unsupported", format);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700394 return -ENOSYS;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700395 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700396 SUBMIX_ALOGV("out_set_format(format=%x)", format);
397 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700398}
399
400static int out_standby(struct audio_stream *stream)
401{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700402 struct submix_audio_device * const rsxadev = audio_stream_get_submix_stream_out(stream)->dev;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700403 ALOGI("out_standby()");
404
Stewart Milesf645c5e2014-05-01 09:03:27 -0700405 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700406
Stewart Milesf645c5e2014-05-01 09:03:27 -0700407 rsxadev->output_standby = true;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700408
Stewart Milesf645c5e2014-05-01 09:03:27 -0700409 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700410
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700411 return 0;
412}
413
414static int out_dump(const struct audio_stream *stream, int fd)
415{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700416 (void)stream;
417 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700418 return 0;
419}
420
421static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
422{
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700423 int exiting = -1;
424 AudioParameter parms = AudioParameter(String8(kvpairs));
Stewart Milesc049a0a2014-05-01 09:03:27 -0700425 SUBMIX_ALOGV("out_set_parameters() kvpairs='%s'", kvpairs);
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700426 // FIXME this is using hard-coded strings but in the future, this functionality will be
427 // converted to use audio HAL extensions required to support tunneling
428 if ((parms.getInt(String8("exiting"), exiting) == NO_ERROR) && (exiting > 0)) {
Stewart Milesf645c5e2014-05-01 09:03:27 -0700429 struct submix_audio_device * const rsxadev =
430 audio_stream_get_submix_stream_out(stream)->dev;
431 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800432 { // using the sink
Stewart Milesf645c5e2014-05-01 09:03:27 -0700433 sp<MonoPipe> sink = rsxadev->rsxSink.get();
434 if (sink == NULL) {
435 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800436 return 0;
437 }
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700438
Stewart Milesc049a0a2014-05-01 09:03:27 -0700439 ALOGI("out_set_parameters(): shutdown");
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800440 sink->shutdown(true);
441 } // done using the sink
Stewart Milesf645c5e2014-05-01 09:03:27 -0700442 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700443 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700444 return 0;
445}
446
447static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
448{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700449 (void)stream;
450 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700451 return strdup("");
452}
453
454static uint32_t out_get_latency(const struct audio_stream_out *stream)
455{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700456 const struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(
457 const_cast<struct audio_stream_out *>(stream));
Stewart Miles568e66f2014-05-01 09:03:27 -0700458 const struct submix_config * const config = &out->dev->config;
Stewart Miles70726842014-05-01 09:03:27 -0700459 const uint32_t latency_ms = (MAX_PIPE_DEPTH_IN_FRAMES * 1000) / config->common.sample_rate;
Stewart Miles568e66f2014-05-01 09:03:27 -0700460 SUBMIX_ALOGV("out_get_latency() returns %u ms, size in frames %zu, sample rate %u", latency_ms,
Stewart Miles70726842014-05-01 09:03:27 -0700461 MAX_PIPE_DEPTH_IN_FRAMES, config->common.sample_rate);
Stewart Miles568e66f2014-05-01 09:03:27 -0700462 return latency_ms;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700463}
464
465static int out_set_volume(struct audio_stream_out *stream, float left,
466 float right)
467{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700468 (void)stream;
469 (void)left;
470 (void)right;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700471 return -ENOSYS;
472}
473
474static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
475 size_t bytes)
476{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700477 SUBMIX_ALOGV("out_write(bytes=%zd)", bytes);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700478 ssize_t written_frames = 0;
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700479 const size_t frame_size = audio_stream_frame_size(&stream->common);
Stewart Milesf645c5e2014-05-01 09:03:27 -0700480 struct submix_audio_device * const rsxadev =
481 audio_stream_out_get_submix_stream_out(stream)->dev;
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700482 const size_t frames = bytes / frame_size;
483
Stewart Milesf645c5e2014-05-01 09:03:27 -0700484 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700485
Stewart Milesf645c5e2014-05-01 09:03:27 -0700486 rsxadev->output_standby = false;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700487
Stewart Milesf645c5e2014-05-01 09:03:27 -0700488 sp<MonoPipe> sink = rsxadev->rsxSink.get();
489 if (sink != NULL) {
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700490 if (sink->isShutdown()) {
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800491 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700492 pthread_mutex_unlock(&rsxadev->lock);
Stewart Milesc049a0a2014-05-01 09:03:27 -0700493 SUBMIX_ALOGV("out_write(): pipe shutdown, ignoring the write.");
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700494 // the pipe has already been shutdown, this buffer will be lost but we must
495 // simulate timing so we don't drain the output faster than realtime
496 usleep(frames * 1000000 / out_get_sample_rate(&stream->common));
497 return bytes;
498 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700499 } else {
Stewart Milesf645c5e2014-05-01 09:03:27 -0700500 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700501 ALOGE("out_write without a pipe!");
502 ALOG_ASSERT("out_write without a pipe!");
503 return 0;
504 }
505
Stewart Milesf645c5e2014-05-01 09:03:27 -0700506 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700507
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700508 written_frames = sink->write(buffer, frames);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800509
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700510 if (written_frames < 0) {
511 if (written_frames == (ssize_t)NEGOTIATE) {
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700512 ALOGE("out_write() write to pipe returned NEGOTIATE");
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700513
Stewart Milesf645c5e2014-05-01 09:03:27 -0700514 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800515 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700516 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700517
518 written_frames = 0;
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700519 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700520 } else {
521 // write() returned UNDERRUN or WOULD_BLOCK, retry
Colin Cross5685a082014-04-18 15:45:42 -0700522 ALOGE("out_write() write to pipe returned unexpected %zd", written_frames);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700523 written_frames = sink->write(buffer, frames);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700524 }
525 }
526
Stewart Milesf645c5e2014-05-01 09:03:27 -0700527 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800528 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700529 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700530
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700531 if (written_frames < 0) {
Colin Cross5685a082014-04-18 15:45:42 -0700532 ALOGE("out_write() failed writing to pipe with %zd", written_frames);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700533 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700534 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700535 const ssize_t written_bytes = written_frames * frame_size;
536 SUBMIX_ALOGV("out_write() wrote %zd bytes %zd frames)", written_bytes, written_frames);
537 return written_bytes;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700538}
539
540static int out_get_render_position(const struct audio_stream_out *stream,
541 uint32_t *dsp_frames)
542{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700543 (void)stream;
544 (void)dsp_frames;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700545 return -EINVAL;
546}
547
548static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
549{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700550 (void)stream;
551 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700552 return 0;
553}
554
555static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
556{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700557 (void)stream;
558 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700559 return 0;
560}
561
562static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
563 int64_t *timestamp)
564{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700565 (void)stream;
566 (void)timestamp;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700567 return -EINVAL;
568}
569
570/** audio_stream_in implementation **/
571static uint32_t in_get_sample_rate(const struct audio_stream *stream)
572{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700573 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
574 const_cast<struct audio_stream*>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700575 SUBMIX_ALOGV("in_get_sample_rate() returns %u", in->dev->config.common.sample_rate);
576 return in->dev->config.common.sample_rate;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700577}
578
579static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
580{
Stewart Miles568e66f2014-05-01 09:03:27 -0700581 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700582 if (!sample_rate_supported(rate)) {
583 ALOGE("in_set_sample_rate(rate=%u) rate unsupported", rate);
584 return -ENOSYS;
585 }
586 in->dev->config.common.sample_rate = rate;
Stewart Miles568e66f2014-05-01 09:03:27 -0700587 SUBMIX_ALOGV("in_set_sample_rate() set %u", rate);
588 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700589}
590
591static size_t in_get_buffer_size(const struct audio_stream *stream)
592{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700593 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
594 const_cast<struct audio_stream*>(stream));
Stewart Miles568e66f2014-05-01 09:03:27 -0700595 const size_t buffer_size = in->dev->config.period_size * audio_stream_frame_size(stream);
596 SUBMIX_ALOGV("in_get_buffer_size() returns %zu", buffer_size);
597 return buffer_size;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700598}
599
600static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
601{
Stewart Miles70726842014-05-01 09:03:27 -0700602 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
603 const_cast<struct audio_stream*>(stream));
604 const audio_channel_mask_t channel_mask = in->dev->config.input_channel_mask;
605 SUBMIX_ALOGV("in_get_channels() returns %x", channel_mask);
606 return channel_mask;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700607}
608
609static audio_format_t in_get_format(const struct audio_stream *stream)
610{
Stewart Miles568e66f2014-05-01 09:03:27 -0700611 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
Stewart Miles70726842014-05-01 09:03:27 -0700612 const_cast<struct audio_stream*>(stream));
613 const audio_format_t format = in->dev->config.common.format;
Stewart Miles568e66f2014-05-01 09:03:27 -0700614 SUBMIX_ALOGV("in_get_format() returns %x", format);
615 return format;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700616}
617
618static int in_set_format(struct audio_stream *stream, audio_format_t format)
619{
Stewart Miles568e66f2014-05-01 09:03:27 -0700620 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700621 if (format != in->dev->config.common.format) {
Stewart Milesc049a0a2014-05-01 09:03:27 -0700622 ALOGE("in_set_format(format=%x) format unsupported", format);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700623 return -ENOSYS;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700624 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700625 SUBMIX_ALOGV("in_set_format(format=%x)", format);
626 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700627}
628
629static int in_standby(struct audio_stream *stream)
630{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700631 struct submix_audio_device * const rsxadev = audio_stream_get_submix_stream_in(stream)->dev;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700632 ALOGI("in_standby()");
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700633
Stewart Milesf645c5e2014-05-01 09:03:27 -0700634 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700635
Stewart Milesf645c5e2014-05-01 09:03:27 -0700636 rsxadev->input_standby = true;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700637
Stewart Milesf645c5e2014-05-01 09:03:27 -0700638 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700639
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700640 return 0;
641}
642
643static int in_dump(const struct audio_stream *stream, int fd)
644{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700645 (void)stream;
646 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700647 return 0;
648}
649
650static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
651{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700652 (void)stream;
653 (void)kvpairs;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700654 return 0;
655}
656
657static char * in_get_parameters(const struct audio_stream *stream,
658 const char *keys)
659{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700660 (void)stream;
661 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700662 return strdup("");
663}
664
665static int in_set_gain(struct audio_stream_in *stream, float gain)
666{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700667 (void)stream;
668 (void)gain;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700669 return 0;
670}
671
672static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
673 size_t bytes)
674{
675 ssize_t frames_read = -1977;
Stewart Milesf645c5e2014-05-01 09:03:27 -0700676 struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream);
677 struct submix_audio_device * const rsxadev = in->dev;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700678 const size_t frame_size = audio_stream_frame_size(&stream->common);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700679 const size_t frames_to_read = bytes / frame_size;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700680
Stewart Milesc049a0a2014-05-01 09:03:27 -0700681 SUBMIX_ALOGV("in_read bytes=%zu", bytes);
Stewart Milesf645c5e2014-05-01 09:03:27 -0700682 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700683
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700684 const bool output_standby_transition = (in->output_standby != in->dev->output_standby);
Stewart Milesf645c5e2014-05-01 09:03:27 -0700685 in->output_standby = rsxadev->output_standby;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700686
Stewart Milesf645c5e2014-05-01 09:03:27 -0700687 if (rsxadev->input_standby || output_standby_transition) {
688 rsxadev->input_standby = false;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700689 // keep track of when we exit input standby (== first read == start "real recording")
690 // or when we start recording silence, and reset projected time
691 int rc = clock_gettime(CLOCK_MONOTONIC, &in->record_start_time);
692 if (rc == 0) {
693 in->read_counter_frames = 0;
694 }
695 }
696
697 in->read_counter_frames += frames_to_read;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700698 size_t remaining_frames = frames_to_read;
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800699
700 {
701 // about to read from audio source
Stewart Milesf645c5e2014-05-01 09:03:27 -0700702 sp<MonoPipeReader> source = rsxadev->rsxSource;
703 if (source == NULL) {
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800704 ALOGE("no audio pipe yet we're trying to read!");
Stewart Milesf645c5e2014-05-01 09:03:27 -0700705 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800706 usleep((bytes / frame_size) * 1000000 / in_get_sample_rate(&stream->common));
707 memset(buffer, 0, bytes);
708 return bytes;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700709 }
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800710
Stewart Milesf645c5e2014-05-01 09:03:27 -0700711 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800712
713 // read the data from the pipe (it's non blocking)
714 int attempts = 0;
715 char* buff = (char*)buffer;
716 while ((remaining_frames > 0) && (attempts < MAX_READ_ATTEMPTS)) {
717 attempts++;
718 frames_read = source->read(buff, remaining_frames, AudioBufferProvider::kInvalidPTS);
719 if (frames_read > 0) {
720 remaining_frames -= frames_read;
721 buff += frames_read * frame_size;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700722 SUBMIX_ALOGV(" in_read (att=%d) got %zd frames, remaining=%zu",
723 attempts, frames_read, remaining_frames);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800724 } else {
Stewart Milesc049a0a2014-05-01 09:03:27 -0700725 SUBMIX_ALOGE(" in_read read returned %zd", frames_read);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800726 usleep(READ_ATTEMPT_SLEEP_MS * 1000);
727 }
728 }
729 // done using the source
Stewart Milesf645c5e2014-05-01 09:03:27 -0700730 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800731 source.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700732 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700733 }
734
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700735 if (remaining_frames > 0) {
Stewart Milesc049a0a2014-05-01 09:03:27 -0700736 SUBMIX_ALOGV(" remaining_frames = %zu", remaining_frames);
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700737 memset(((char*)buffer)+ bytes - (remaining_frames * frame_size), 0,
738 remaining_frames * frame_size);
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700739 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700740
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700741 // compute how much we need to sleep after reading the data by comparing the wall clock with
742 // the projected time at which we should return.
743 struct timespec time_after_read;// wall clock after reading from the pipe
744 struct timespec record_duration;// observed record duration
745 int rc = clock_gettime(CLOCK_MONOTONIC, &time_after_read);
746 const uint32_t sample_rate = in_get_sample_rate(&stream->common);
747 if (rc == 0) {
748 // for how long have we been recording?
749 record_duration.tv_sec = time_after_read.tv_sec - in->record_start_time.tv_sec;
750 record_duration.tv_nsec = time_after_read.tv_nsec - in->record_start_time.tv_nsec;
751 if (record_duration.tv_nsec < 0) {
752 record_duration.tv_sec--;
753 record_duration.tv_nsec += 1000000000;
754 }
755
Stewart Milesf645c5e2014-05-01 09:03:27 -0700756 // read_counter_frames contains the number of frames that have been read since the
757 // beginning of recording (including this call): it's converted to usec and compared to
758 // how long we've been recording for, which gives us how long we must wait to sync the
759 // projected recording time, and the observed recording time.
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700760 long projected_vs_observed_offset_us =
761 ((int64_t)(in->read_counter_frames
762 - (record_duration.tv_sec*sample_rate)))
763 * 1000000 / sample_rate
764 - (record_duration.tv_nsec / 1000);
765
Stewart Milesc049a0a2014-05-01 09:03:27 -0700766 SUBMIX_ALOGV(" record duration %5lds %3ldms, will wait: %7ldus",
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700767 record_duration.tv_sec, record_duration.tv_nsec/1000000,
768 projected_vs_observed_offset_us);
769 if (projected_vs_observed_offset_us > 0) {
770 usleep(projected_vs_observed_offset_us);
771 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700772 }
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700773
Stewart Milesc049a0a2014-05-01 09:03:27 -0700774 SUBMIX_ALOGV("in_read returns %zu", bytes);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700775 return bytes;
776
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700777}
778
779static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
780{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700781 (void)stream;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700782 return 0;
783}
784
785static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
786{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700787 (void)stream;
788 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700789 return 0;
790}
791
792static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
793{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700794 (void)stream;
795 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700796 return 0;
797}
798
799static int adev_open_output_stream(struct audio_hw_device *dev,
800 audio_io_handle_t handle,
801 audio_devices_t devices,
802 audio_output_flags_t flags,
803 struct audio_config *config,
804 struct audio_stream_out **stream_out)
805{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700806 struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700807 ALOGV("adev_open_output_stream()");
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700808 struct submix_stream_out *out;
809 int ret;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700810 (void)handle;
811 (void)devices;
812 (void)flags;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700813
Stewart Miles70726842014-05-01 09:03:27 -0700814 // Make sure it's possible to open the device given the current audio config.
815 submix_sanitize_config(config, false);
816 if (!submix_open_validate(rsxadev, &rsxadev->lock, config, false)) {
817 ALOGE("adev_open_output_stream(): Unable to open output stream.");
818 return -EINVAL;
819 }
820
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700821 out = (struct submix_stream_out *)calloc(1, sizeof(struct submix_stream_out));
822 if (!out) {
823 ret = -ENOMEM;
824 goto err_open;
825 }
826
827 pthread_mutex_lock(&rsxadev->lock);
828
Stewart Miles568e66f2014-05-01 09:03:27 -0700829 // Initialize the function pointer tables (v-tables).
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700830 out->stream.common.get_sample_rate = out_get_sample_rate;
831 out->stream.common.set_sample_rate = out_set_sample_rate;
832 out->stream.common.get_buffer_size = out_get_buffer_size;
833 out->stream.common.get_channels = out_get_channels;
834 out->stream.common.get_format = out_get_format;
835 out->stream.common.set_format = out_set_format;
836 out->stream.common.standby = out_standby;
837 out->stream.common.dump = out_dump;
838 out->stream.common.set_parameters = out_set_parameters;
839 out->stream.common.get_parameters = out_get_parameters;
840 out->stream.common.add_audio_effect = out_add_audio_effect;
841 out->stream.common.remove_audio_effect = out_remove_audio_effect;
842 out->stream.get_latency = out_get_latency;
843 out->stream.set_volume = out_set_volume;
844 out->stream.write = out_write;
845 out->stream.get_render_position = out_get_render_position;
846 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
847
Stewart Miles70726842014-05-01 09:03:27 -0700848 memcpy(&rsxadev->config.common, config, sizeof(rsxadev->config.common));
849 rsxadev->config.output_channel_mask = config->channel_mask;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700850
Stewart Miles568e66f2014-05-01 09:03:27 -0700851 rsxadev->config.period_size = PERIOD_SIZE_IN_FRAMES;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700852
Stewart Miles568e66f2014-05-01 09:03:27 -0700853 // Store a pointer to the device from the output stream.
854 out->dev = rsxadev;
855 // Return the output stream.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700856 *stream_out = &out->stream;
857
Stewart Miles568e66f2014-05-01 09:03:27 -0700858
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700859 // initialize pipe
860 {
861 ALOGV(" initializing pipe");
Stewart Miles70726842014-05-01 09:03:27 -0700862 const NBAIO_Format format = Format_from_SR_C(rsxadev->config.common.sample_rate,
863 get_channel_count_from_mask(rsxadev->config.common.channel_mask),
864 rsxadev->config.common.format);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700865 const NBAIO_Format offers[1] = {format};
866 size_t numCounterOffers = 0;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700867 // creating a MonoPipe with optional blocking set to true.
868 MonoPipe* sink = new MonoPipe(MAX_PIPE_DEPTH_IN_FRAMES, format, true/*writeCanBlock*/);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700869 ssize_t index = sink->negotiate(offers, 1, NULL, numCounterOffers);
870 ALOG_ASSERT(index == 0);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700871 MonoPipeReader* source = new MonoPipeReader(sink);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700872 numCounterOffers = 0;
873 index = source->negotiate(offers, 1, NULL, numCounterOffers);
874 ALOG_ASSERT(index == 0);
875 rsxadev->rsxSink = sink;
876 rsxadev->rsxSource = source;
877 }
878
879 pthread_mutex_unlock(&rsxadev->lock);
880
881 return 0;
882
883err_open:
884 *stream_out = NULL;
885 return ret;
886}
887
888static void adev_close_output_stream(struct audio_hw_device *dev,
889 struct audio_stream_out *stream)
890{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700891 struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700892 ALOGV("adev_close_output_stream()");
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700893
894 pthread_mutex_lock(&rsxadev->lock);
895
896 rsxadev->rsxSink.clear();
897 rsxadev->rsxSource.clear();
898 free(stream);
899
900 pthread_mutex_unlock(&rsxadev->lock);
901}
902
903static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
904{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700905 (void)dev;
906 (void)kvpairs;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700907 return -ENOSYS;
908}
909
910static char * adev_get_parameters(const struct audio_hw_device *dev,
911 const char *keys)
912{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700913 (void)dev;
914 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700915 return strdup("");;
916}
917
918static int adev_init_check(const struct audio_hw_device *dev)
919{
920 ALOGI("adev_init_check()");
Stewart Milesc049a0a2014-05-01 09:03:27 -0700921 (void)dev;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700922 return 0;
923}
924
925static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
926{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700927 (void)dev;
928 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700929 return -ENOSYS;
930}
931
932static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
933{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700934 (void)dev;
935 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700936 return -ENOSYS;
937}
938
939static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
940{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700941 (void)dev;
942 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700943 return -ENOSYS;
944}
945
946static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
947{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700948 (void)dev;
949 (void)muted;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700950 return -ENOSYS;
951}
952
953static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
954{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700955 (void)dev;
956 (void)muted;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700957 return -ENOSYS;
958}
959
960static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
961{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700962 (void)dev;
963 (void)mode;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700964 return 0;
965}
966
967static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
968{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700969 (void)dev;
970 (void)state;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700971 return -ENOSYS;
972}
973
974static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
975{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700976 (void)dev;
977 (void)state;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700978 return -ENOSYS;
979}
980
981static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
982 const struct audio_config *config)
983{
Stewart Miles568e66f2014-05-01 09:03:27 -0700984 if (audio_is_linear_pcm(config->format)) {
985 const size_t buffer_period_size_frames =
986 audio_hw_device_get_submix_audio_device(const_cast<struct audio_hw_device*>(dev))->
987 config.period_size;
988 const size_t frame_size_in_bytes = get_channel_count_from_mask(config->channel_mask) *
989 audio_bytes_per_sample(config->format);
990 const size_t buffer_size = buffer_period_size_frames * frame_size_in_bytes;
991 SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames",
992 buffer_size, buffer_period_size_frames);
993 return buffer_size;
994 }
995 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700996}
997
998static int adev_open_input_stream(struct audio_hw_device *dev,
999 audio_io_handle_t handle,
1000 audio_devices_t devices,
1001 struct audio_config *config,
1002 struct audio_stream_in **stream_in)
1003{
Stewart Milesf645c5e2014-05-01 09:03:27 -07001004 struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001005 struct submix_stream_in *in;
1006 int ret;
Stewart Miles568e66f2014-05-01 09:03:27 -07001007 ALOGI("adev_open_input_stream()");
Stewart Milesc049a0a2014-05-01 09:03:27 -07001008 (void)handle;
1009 (void)devices;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001010
Stewart Miles70726842014-05-01 09:03:27 -07001011 // Make sure it's possible to open the device given the current audio config.
1012 submix_sanitize_config(config, true);
1013 if (!submix_open_validate(rsxadev, &rsxadev->lock, config, true)) {
1014 ALOGE("adev_open_input_stream(): Unable to open input stream.");
1015 return -EINVAL;
1016 }
1017
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001018 in = (struct submix_stream_in *)calloc(1, sizeof(struct submix_stream_in));
1019 if (!in) {
1020 ret = -ENOMEM;
1021 goto err_open;
1022 }
1023
1024 pthread_mutex_lock(&rsxadev->lock);
1025
Stewart Miles568e66f2014-05-01 09:03:27 -07001026 // Initialize the function pointer tables (v-tables).
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001027 in->stream.common.get_sample_rate = in_get_sample_rate;
1028 in->stream.common.set_sample_rate = in_set_sample_rate;
1029 in->stream.common.get_buffer_size = in_get_buffer_size;
1030 in->stream.common.get_channels = in_get_channels;
1031 in->stream.common.get_format = in_get_format;
1032 in->stream.common.set_format = in_set_format;
1033 in->stream.common.standby = in_standby;
1034 in->stream.common.dump = in_dump;
1035 in->stream.common.set_parameters = in_set_parameters;
1036 in->stream.common.get_parameters = in_get_parameters;
1037 in->stream.common.add_audio_effect = in_add_audio_effect;
1038 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1039 in->stream.set_gain = in_set_gain;
1040 in->stream.read = in_read;
1041 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1042
Stewart Miles70726842014-05-01 09:03:27 -07001043 memcpy(&rsxadev->config.common, config, sizeof(rsxadev->config.common));
1044 rsxadev->config.input_channel_mask = config->channel_mask;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001045
Stewart Miles568e66f2014-05-01 09:03:27 -07001046 rsxadev->config.period_size = PERIOD_SIZE_IN_FRAMES;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001047
1048 *stream_in = &in->stream;
1049
1050 in->dev = rsxadev;
1051
Stewart Miles568e66f2014-05-01 09:03:27 -07001052 // Initialize the input stream.
Jean-Michel Trivieec87702012-09-17 09:59:42 -07001053 in->read_counter_frames = 0;
1054 in->output_standby = rsxadev->output_standby;
1055
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001056 pthread_mutex_unlock(&rsxadev->lock);
1057
1058 return 0;
1059
1060err_open:
1061 *stream_in = NULL;
1062 return ret;
1063}
1064
1065static void adev_close_input_stream(struct audio_hw_device *dev,
Stewart Milesc049a0a2014-05-01 09:03:27 -07001066 struct audio_stream_in *stream)
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001067{
Stewart Milesf645c5e2014-05-01 09:03:27 -07001068 struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001069 ALOGV("adev_close_input_stream()");
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001070
1071 pthread_mutex_lock(&rsxadev->lock);
1072
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -07001073 MonoPipe* sink = rsxadev->rsxSink.get();
1074 if (sink != NULL) {
1075 ALOGI("shutdown");
1076 sink->shutdown(true);
1077 }
1078
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001079 free(stream);
1080
1081 pthread_mutex_unlock(&rsxadev->lock);
1082}
1083
1084static int adev_dump(const audio_hw_device_t *device, int fd)
1085{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001086 (void)device;
1087 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001088 return 0;
1089}
1090
1091static int adev_close(hw_device_t *device)
1092{
1093 ALOGI("adev_close()");
1094 free(device);
1095 return 0;
1096}
1097
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001098static int adev_open(const hw_module_t* module, const char* name,
1099 hw_device_t** device)
1100{
1101 ALOGI("adev_open(name=%s)", name);
1102 struct submix_audio_device *rsxadev;
1103
1104 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1105 return -EINVAL;
1106
1107 rsxadev = (submix_audio_device*) calloc(1, sizeof(struct submix_audio_device));
1108 if (!rsxadev)
1109 return -ENOMEM;
1110
1111 rsxadev->device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent5d85c532012-09-10 10:36:09 -07001112 rsxadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001113 rsxadev->device.common.module = (struct hw_module_t *) module;
1114 rsxadev->device.common.close = adev_close;
1115
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001116 rsxadev->device.init_check = adev_init_check;
1117 rsxadev->device.set_voice_volume = adev_set_voice_volume;
1118 rsxadev->device.set_master_volume = adev_set_master_volume;
1119 rsxadev->device.get_master_volume = adev_get_master_volume;
1120 rsxadev->device.set_master_mute = adev_set_master_mute;
1121 rsxadev->device.get_master_mute = adev_get_master_mute;
1122 rsxadev->device.set_mode = adev_set_mode;
1123 rsxadev->device.set_mic_mute = adev_set_mic_mute;
1124 rsxadev->device.get_mic_mute = adev_get_mic_mute;
1125 rsxadev->device.set_parameters = adev_set_parameters;
1126 rsxadev->device.get_parameters = adev_get_parameters;
1127 rsxadev->device.get_input_buffer_size = adev_get_input_buffer_size;
1128 rsxadev->device.open_output_stream = adev_open_output_stream;
1129 rsxadev->device.close_output_stream = adev_close_output_stream;
1130 rsxadev->device.open_input_stream = adev_open_input_stream;
1131 rsxadev->device.close_input_stream = adev_close_input_stream;
1132 rsxadev->device.dump = adev_dump;
1133
Jean-Michel Trivieec87702012-09-17 09:59:42 -07001134 rsxadev->input_standby = true;
1135 rsxadev->output_standby = true;
1136
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001137 *device = &rsxadev->device.common;
1138
1139 return 0;
1140}
1141
1142static struct hw_module_methods_t hal_module_methods = {
1143 /* open */ adev_open,
1144};
1145
1146struct audio_module HAL_MODULE_INFO_SYM = {
1147 /* common */ {
1148 /* tag */ HARDWARE_MODULE_TAG,
1149 /* module_api_version */ AUDIO_MODULE_API_VERSION_0_1,
1150 /* hal_api_version */ HARDWARE_HAL_API_VERSION,
1151 /* id */ AUDIO_HARDWARE_MODULE_ID,
1152 /* name */ "Wifi Display audio HAL",
1153 /* author */ "The Android Open Source Project",
1154 /* methods */ &hal_module_methods,
1155 /* dso */ NULL,
1156 /* reserved */ { 0 },
1157 },
1158};
1159
1160} //namespace android
1161
1162} //extern "C"