188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi/* 288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * Copyright (C) 2012 The Android Open Source Project 388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * 488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * you may not use this file except in compliance with the License. 688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * You may obtain a copy of the License at 788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * 888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * 1088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 1188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 1288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * See the License for the specific language governing permissions and 1488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * limitations under the License. 1588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi */ 1688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#define LOG_TAG "r_submix" 1835a2c167b4ee090b5dd9779ecb40f82cdaf1c74dJean-Michel Trivi//#define LOG_NDEBUG 0 1988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 2088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <errno.h> 2188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <pthread.h> 2288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <stdint.h> 2388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <stdlib.h> 24c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <sys/param.h> 25c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <sys/time.h> 26e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#include <sys/limits.h> 2788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 2825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi#include <cutils/compiler.h> 2988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <cutils/log.h> 3088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <cutils/properties.h> 31c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <cutils/str_parms.h> 3288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 33c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <hardware/audio.h> 3488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <hardware/hardware.h> 3588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <system/audio.h> 3688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 37c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <media/AudioParameter.h> 38c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <media/AudioBufferProvider.h> 39eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi#include <media/nbaio/MonoPipe.h> 40eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi#include <media/nbaio/MonoPipeReader.h> 4188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 42d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi#include <utils/String8.h> 43d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi 4492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAMS_TO_FILES 0 4592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 4692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#include <fcntl.h> 4792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#include <stdio.h> 4892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#include <sys/stat.h> 4992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 5092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles 5188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Triviextern "C" { 5288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 5388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivinamespace android { 5488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 55c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles// Set to 1 to enable extremely verbose logging in this module. 56c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_VERBOSE_LOGGING 0 57c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#if SUBMIX_VERBOSE_LOGGING 58c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGV(...) ALOGV(__VA_ARGS__) 59c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGE(...) ALOGE(__VA_ARGS__) 60c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#else 61c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGV(...) 62c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGE(...) 63c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#endif // SUBMIX_VERBOSE_LOGGING 64c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles 653dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe(). 66bbb3e77ab0ca247c646d4a0f9d815bd6754d8ebaJean-Michel Trivi#define DEFAULT_PIPE_SIZE_IN_FRAMES (1024*4) 673dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Value used to divide the MonoPipe() buffer into segments that are written to the source and 683dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// read from the sink. The maximum latency of the device is the size of the MonoPipe's buffer 693dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// the minimum latency is the MonoPipe buffer size divided by this value. 703dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#define DEFAULT_PIPE_PERIOD_COUNT 4 71eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi// The duration of MAX_READ_ATTEMPTS * READ_ATTEMPT_SLEEP_MS must be stricly inferior to 72eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi// the duration of a record buffer at the current record sample rate (of the device, not of 73eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi// the recording itself). Here we have: 74eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi// 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms 756acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi#define MAX_READ_ATTEMPTS 3 76eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi#define READ_ATTEMPT_SLEEP_MS 5 // 5ms between two read attempts when pipe is empty 77568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles#define DEFAULT_SAMPLE_RATE_HZ 48000 // default sample rate 78568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles// See NBAIO_Format frameworks/av/include/media/nbaio/NBAIO.h. 79568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles#define DEFAULT_FORMAT AUDIO_FORMAT_PCM_16_BIT 803dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// A legacy user of this device does not close the input stream when it shuts down, which 813dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// results in the application opening a new input stream before closing the old input stream 823dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// handle it was previously using. Setting this value to 1 allows multiple clients to open 833dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// multiple input streams from this device. If this option is enabled, each input stream returned 843dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// is *the same stream* which means that readers will race to read data from these streams. 853dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#define ENABLE_LEGACY_INPUT_OPEN 1 86e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles// Whether channel conversion (16-bit signed PCM mono->stereo, stereo->mono) is enabled. 87e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#define ENABLE_CHANNEL_CONVERSION 1 8802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles// Whether resampling is enabled. 8902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#define ENABLE_RESAMPLING 1 9092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 9192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles// Folder to save stream log files to. 92854a10af10df54eb09946d8a39c9188939d57093Eric Laurent#define LOG_STREAM_FOLDER "/data/misc/audioserver" 9392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles// Log filenames for input and output streams. 9492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAM_OUT_FILENAME LOG_STREAM_FOLDER "/r_submix_out.raw" 9592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAM_IN_FILENAME LOG_STREAM_FOLDER "/r_submix_in.raw" 9692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles// File permissions for stream log files. 9792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAM_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 9892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 99793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi// limit for number of read error log entries to avoid spamming the logs 100793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi#define MAX_READ_ERROR_LOGS 5 1013dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 1023dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Common limits macros. 1033dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#ifndef min 1043dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#define min(a, b) ((a) < (b) ? (a) : (b)) 1053dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // min 106e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#ifndef max 107e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#define max(a, b) ((a) > (b) ? (a) : (b)) 108e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // max 10988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1107072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Set *result_variable_ptr to true if value_to_find is present in the array array_to_search, 1117072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// otherwise set *result_variable_ptr to false. 1127072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles#define SUBMIX_VALUE_IN_SET(value_to_find, array_to_search, result_variable_ptr) \ 1137072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles { \ 1147072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles size_t i; \ 1157072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles *(result_variable_ptr) = false; \ 1167072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles for (i = 0; i < sizeof(array_to_search) / sizeof((array_to_search)[0]); i++) { \ 1177072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles if ((value_to_find) == (array_to_search)[i]) { \ 1187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles *(result_variable_ptr) = true; \ 1197072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles break; \ 1207072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } \ 1217072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } \ 1227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 1237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 124568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles// Configuration of the submix pipe. 12588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct submix_config { 1267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Channel mask field in this data structure is set to either input_channel_mask or 1277072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // output_channel_mask depending upon the last stream to be opened on this device. 1287072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles struct audio_config common; 1297072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Input stream and output stream channel masks. This is required since input and output 1307072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // channel bitfields are not equivalent. 1317072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles audio_channel_mask_t input_channel_mask; 1327072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles audio_channel_mask_t output_channel_mask; 13302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 13402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Input stream and output stream sample rates. 13502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles uint32_t input_sample_rate; 13602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles uint32_t output_sample_rate; 13702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 138e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles size_t pipe_frame_size; // Number of bytes in each audio frame in the pipe. 1393dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles size_t buffer_size_frames; // Size of the audio pipe in frames. 1403dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Maximum number of frames buffered by the input and output streams. 1413dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles size_t buffer_period_size_frames; 14288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}; 14388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 144b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#define MAX_ROUTES 10 145b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivitypedef struct route_config { 146b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_config config; 147b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; 14888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi // Pipe variables: they handle the ring buffer that "pipes" audio: 149eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // - from the submix virtual audio output == what needs to be played 150eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // remotely, seen as an output for AudioFlinger 15188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi // - to the virtual audio source == what is captured by the component 15288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi // which "records" the submix / virtual audio source, and handles it as needed. 153eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // A usecase example is one where the component capturing the audio is then sending it over 15488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a 15588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi // TV with Wifi Display capabilities), or to a wireless audio player. 156568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles sp<MonoPipe> rsxSink; 157eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi sp<MonoPipeReader> rsxSource; 158b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // Pointers to the current input and output stream instances. rsxSink and rsxSource are 159b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // destroyed if both and input and output streams are destroyed. 160b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_stream_out *output; 161b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_stream_in *input; 16202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 16302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Buffer used as temporary storage for resampled data prior to returning data to the output 16402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // stream. 16502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles int16_t resampler_buffer[DEFAULT_PIPE_SIZE_IN_FRAMES]; 16602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 167b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi} route_config_t; 16888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 169b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistruct submix_audio_device { 170b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct audio_hw_device device; 171b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi route_config_t routes[MAX_ROUTES]; 172568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles // Device lock, also used to protect access to submix_audio_device from the input and output 173568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles // streams. 17488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi pthread_mutex_t lock; 17588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}; 17688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 17788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct submix_stream_out { 17888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct audio_stream_out stream; 17988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct submix_audio_device *dev; 180b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_handle; 181b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi bool output_standby; 1820b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung uint64_t frames_written; 1830b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung uint64_t frames_written_since_standby; 18492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 18592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles int log_fd; 18692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 18788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}; 18888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 18988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct submix_stream_in { 19088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct audio_stream_in stream; 19188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct submix_audio_device *dev; 192b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_handle; 193b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi bool input_standby; 194b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi bool output_standby_rec_thr; // output standby state as seen from record thread 195eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // wall clock when recording starts 196eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi struct timespec record_start_time; 197eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // how many frames have been requested to be read 19825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi uint64_t read_counter_frames; 1993dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 2003dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN 2013dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Number of references to this input stream. 2023dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles volatile int32_t ref_count; 2033dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN 20492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 20592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles int log_fd; 20692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 207793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi 208793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi volatile int16_t read_error_count; 209eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi}; 2106acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi 2117072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified sample rate is supported by the submix module. 2127072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool sample_rate_supported(const uint32_t sample_rate) 2137072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 2147072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Set of sample rates supported by Format_from_SR_C() frameworks/av/media/libnbaio/NAIO.cpp. 2157072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles static const unsigned int supported_sample_rates[] = { 2167072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 2177072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles }; 2187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles bool return_value; 2197072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles SUBMIX_VALUE_IN_SET(sample_rate, supported_sample_rates, &return_value); 2207072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return return_value; 2217072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 2227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 2237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified sample rate is supported, if it is return the specified sample 2247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// rate, otherwise return the default sample rate for the submix module. 2257072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic uint32_t get_supported_sample_rate(uint32_t sample_rate) 2267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 2277072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return sample_rate_supported(sample_rate) ? sample_rate : DEFAULT_SAMPLE_RATE_HZ; 2287072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 2297072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 2307072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel in mask is supported by the submix module. 2317072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool channel_in_mask_supported(const audio_channel_mask_t channel_in_mask) 2327072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 2337072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Set of channel in masks supported by Format_from_SR_C() 2347072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // frameworks/av/media/libnbaio/NAIO.cpp. 2357072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles static const audio_channel_mask_t supported_channel_in_masks[] = { 2367072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles AUDIO_CHANNEL_IN_MONO, AUDIO_CHANNEL_IN_STEREO, 2377072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles }; 2387072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles bool return_value; 2397072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles SUBMIX_VALUE_IN_SET(channel_in_mask, supported_channel_in_masks, &return_value); 2407072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return return_value; 2417072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 2427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 2437072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel in mask is supported, if it is return the specified 2447072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// channel in mask, otherwise return the default channel in mask for the submix module. 2457072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic audio_channel_mask_t get_supported_channel_in_mask( 2467072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const audio_channel_mask_t channel_in_mask) 2477072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 2487072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return channel_in_mask_supported(channel_in_mask) ? channel_in_mask : 2497072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_IN_STEREO); 2507072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 2517072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 2527072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel out mask is supported by the submix module. 2537072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool channel_out_mask_supported(const audio_channel_mask_t channel_out_mask) 2547072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 2557072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Set of channel out masks supported by Format_from_SR_C() 2567072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // frameworks/av/media/libnbaio/NAIO.cpp. 2577072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles static const audio_channel_mask_t supported_channel_out_masks[] = { 2587072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO, 2597072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles }; 2607072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles bool return_value; 2617072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles SUBMIX_VALUE_IN_SET(channel_out_mask, supported_channel_out_masks, &return_value); 2627072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return return_value; 2637072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 2647072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 2657072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel out mask is supported, if it is return the specified 2667072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// channel out mask, otherwise return the default channel out mask for the submix module. 2677072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic audio_channel_mask_t get_supported_channel_out_mask( 2687072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const audio_channel_mask_t channel_out_mask) 2697072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 2707072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return channel_out_mask_supported(channel_out_mask) ? channel_out_mask : 2717072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_OUT_STEREO); 2727072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 2737072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 274f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_out given an audio_stream_out that is embedded within the 275f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// structure. 276f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_out * audio_stream_out_get_submix_stream_out( 277f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct audio_stream_out * const stream) 278f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{ 279f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles ALOG_ASSERT(stream); 280f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles return reinterpret_cast<struct submix_stream_out *>(reinterpret_cast<uint8_t *>(stream) - 281f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles offsetof(struct submix_stream_out, stream)); 282f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles} 283f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles 284f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_out given an audio_stream that is embedded within the structure. 285f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_out * audio_stream_get_submix_stream_out( 286f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct audio_stream * const stream) 287f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{ 288f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles ALOG_ASSERT(stream); 289f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles return audio_stream_out_get_submix_stream_out( 290f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles reinterpret_cast<struct audio_stream_out *>(stream)); 291f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles} 292f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles 293f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_in given an audio_stream_in that is embedded within the 294f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// structure. 295f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_in * audio_stream_in_get_submix_stream_in( 296f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct audio_stream_in * const stream) 297f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{ 298f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles ALOG_ASSERT(stream); 299f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles return reinterpret_cast<struct submix_stream_in *>(reinterpret_cast<uint8_t *>(stream) - 300f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles offsetof(struct submix_stream_in, stream)); 301f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles} 302f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles 303f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_in given an audio_stream that is embedded within the structure. 304f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_in * audio_stream_get_submix_stream_in( 305f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct audio_stream * const stream) 306f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{ 307f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles ALOG_ASSERT(stream); 308f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles return audio_stream_in_get_submix_stream_in( 309f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles reinterpret_cast<struct audio_stream_in *>(stream)); 310f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles} 311f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles 312f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_audio_device given a pointer to an audio_device that is embedded within 313f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// the structure. 314f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_audio_device * audio_hw_device_get_submix_audio_device( 315f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct audio_hw_device *device) 316f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{ 317f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles ALOG_ASSERT(device); 318f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles return reinterpret_cast<struct submix_audio_device *>(reinterpret_cast<uint8_t *>(device) - 319f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles offsetof(struct submix_audio_device, device)); 320f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles} 321f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles 3227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Compare an audio_config with input channel mask and an audio_config with output channel mask 3237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// returning false if they do *not* match, true otherwise. 3247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool audio_config_compare(const audio_config * const input_config, 3257072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const audio_config * const output_config) 3267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 327e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if !ENABLE_CHANNEL_CONVERSION 328dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent const uint32_t input_channels = audio_channel_count_from_in_mask(input_config->channel_mask); 329dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent const uint32_t output_channels = audio_channel_count_from_out_mask(output_config->channel_mask); 3303dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (input_channels != output_channels) { 3313dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles ALOGE("audio_config_compare() channel count mismatch input=%d vs. output=%d", 3323dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles input_channels, output_channels); 3337072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return false; 3347072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 335e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // !ENABLE_CHANNEL_CONVERSION 33602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 33702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles if (input_config->sample_rate != output_config->sample_rate && 338dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent audio_channel_count_from_in_mask(input_config->channel_mask) != 1) { 33902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#else 3407072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles if (input_config->sample_rate != output_config->sample_rate) { 34102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 3427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles ALOGE("audio_config_compare() sample rate mismatch %ul vs. %ul", 3437072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles input_config->sample_rate, output_config->sample_rate); 3447072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return false; 3457072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 3467072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles if (input_config->format != output_config->format) { 3477072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles ALOGE("audio_config_compare() format mismatch %x vs. %x", 3487072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles input_config->format, output_config->format); 3497072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return false; 3507072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 3517072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // This purposely ignores offload_info as it's not required for the submix device. 3527072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return true; 3537072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 3547072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 3553dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// If one doesn't exist, create a pipe for the submix audio device rsxadev of size 3563dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// buffer_size_frames and optionally associate "in" or "out" with the submix audio device. 357b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device 358b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic void submix_audio_device_create_pipe_l(struct submix_audio_device * const rsxadev, 3593dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const struct audio_config * const config, 3603dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const size_t buffer_size_frames, 3613dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const uint32_t buffer_period_count, 3623dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles struct submix_stream_in * const in, 363b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_stream_out * const out, 364b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const char *address, 365b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_idx) 3663dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles{ 3673dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles ALOG_ASSERT(in || out); 368b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(route_idx > -1); 369b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(route_idx < MAX_ROUTES); 370b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGD("submix_audio_device_create_pipe_l(addr=%s, idx=%d)", address, route_idx); 371b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 3723dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Save a reference to the specified input or output stream and the associated channel 3733dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // mask. 3743dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (in) { 375b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->route_handle = route_idx; 376b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].input = in; 377b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].config.input_channel_mask = config->channel_mask; 37802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 379b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].config.input_sample_rate = config->sample_rate; 38002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // If the output isn't configured yet, set the output sample rate to the maximum supported 381b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // sample rate such that the smallest possible input buffer is created, and put a default 382b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // value for channel count 383b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (!rsxadev->routes[route_idx].output) { 384b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].config.output_sample_rate = 48000; 385b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].config.output_channel_mask = AUDIO_CHANNEL_OUT_STEREO; 38602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles } 38702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 3883dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 3893dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (out) { 390b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi out->route_handle = route_idx; 391b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].output = out; 392b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].config.output_channel_mask = config->channel_mask; 39302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 394b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].config.output_sample_rate = config->sample_rate; 39502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 3963dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 397b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // Save the address 398b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi strncpy(rsxadev->routes[route_idx].address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN); 399b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGD(" now using address %s for route %d", rsxadev->routes[route_idx].address, route_idx); 4003dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // If a pipe isn't associated with the device, create one. 401b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rsxadev->routes[route_idx].rsxSink == NULL || rsxadev->routes[route_idx].rsxSource == NULL) 402b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi { 403b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_config * const device_config = &rsxadev->routes[route_idx].config; 404dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent uint32_t channel_count; 405dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent if (out) 406dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent channel_count = audio_channel_count_from_out_mask(config->channel_mask); 407dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent else 408dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent channel_count = audio_channel_count_from_in_mask(config->channel_mask); 40910f1a806e6537835de7f71dbc05db1889436732eStewart Miles#if ENABLE_CHANNEL_CONVERSION 41010f1a806e6537835de7f71dbc05db1889436732eStewart Miles // If channel conversion is enabled, allocate enough space for the maximum number of 41110f1a806e6537835de7f71dbc05db1889436732eStewart Miles // possible channels stored in the pipe for the situation when the number of channels in 41210f1a806e6537835de7f71dbc05db1889436732eStewart Miles // the output stream don't match the number in the input stream. 41310f1a806e6537835de7f71dbc05db1889436732eStewart Miles const uint32_t pipe_channel_count = max(channel_count, 2); 41410f1a806e6537835de7f71dbc05db1889436732eStewart Miles#else 41510f1a806e6537835de7f71dbc05db1889436732eStewart Miles const uint32_t pipe_channel_count = channel_count; 41610f1a806e6537835de7f71dbc05db1889436732eStewart Miles#endif // ENABLE_CHANNEL_CONVERSION 41710f1a806e6537835de7f71dbc05db1889436732eStewart Miles const NBAIO_Format format = Format_from_SR_C(config->sample_rate, pipe_channel_count, 41810f1a806e6537835de7f71dbc05db1889436732eStewart Miles config->format); 4193dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const NBAIO_Format offers[1] = {format}; 4203dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles size_t numCounterOffers = 0; 4213dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Create a MonoPipe with optional blocking set to true. 4223dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles MonoPipe* sink = new MonoPipe(buffer_size_frames, format, true /*writeCanBlock*/); 4233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Negotiation between the source and sink cannot fail as the device open operation 4243dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // creates both ends of the pipe using the same audio format. 4253dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles ssize_t index = sink->negotiate(offers, 1, NULL, numCounterOffers); 4263dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles ALOG_ASSERT(index == 0); 4273dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles MonoPipeReader* source = new MonoPipeReader(sink); 4283dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles numCounterOffers = 0; 4293dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles index = source->negotiate(offers, 1, NULL, numCounterOffers); 4303dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles ALOG_ASSERT(index == 0); 431b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGV("submix_audio_device_create_pipe_l(): created pipe"); 4323dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 4333dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Save references to the source and sink. 434b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(rsxadev->routes[route_idx].rsxSink == NULL); 435b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(rsxadev->routes[route_idx].rsxSource == NULL); 436b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].rsxSink = sink; 437b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].rsxSource = source; 4383dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Store the sanitized audio format in the device so that it's possible to determine 4393dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // the format of the pipe source when opening the input device. 4403dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles memcpy(&device_config->common, config, sizeof(device_config->common)); 4413dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles device_config->buffer_size_frames = sink->maxFrames(); 4423dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles device_config->buffer_period_size_frames = device_config->buffer_size_frames / 4433dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles buffer_period_count; 444c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent if (in) device_config->pipe_frame_size = audio_stream_in_frame_size(&in->stream); 445c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent if (out) device_config->pipe_frame_size = audio_stream_out_frame_size(&out->stream); 44610f1a806e6537835de7f71dbc05db1889436732eStewart Miles#if ENABLE_CHANNEL_CONVERSION 44710f1a806e6537835de7f71dbc05db1889436732eStewart Miles // Calculate the pipe frame size based upon the number of channels. 44810f1a806e6537835de7f71dbc05db1889436732eStewart Miles device_config->pipe_frame_size = (device_config->pipe_frame_size * pipe_channel_count) / 44910f1a806e6537835de7f71dbc05db1889436732eStewart Miles channel_count; 45010f1a806e6537835de7f71dbc05db1889436732eStewart Miles#endif // ENABLE_CHANNEL_CONVERSION 451b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi SUBMIX_ALOGV("submix_audio_device_create_pipe_l(): pipe frame size %zd, pipe size %zd, " 452e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles "period size %zd", device_config->pipe_frame_size, 453e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles device_config->buffer_size_frames, device_config->buffer_period_size_frames); 4543dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 4553dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles} 4563dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 4573dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Release references to the sink and source. Input and output threads may maintain references 4583dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// to these objects via StrongPointer (sp<MonoPipe> and sp<MonoPipeReader>) which they can use 4593dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// before they shutdown. 460b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device 461b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic void submix_audio_device_release_pipe_l(struct submix_audio_device * const rsxadev, 462b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_idx) 463b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi{ 464b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(route_idx > -1); 465b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(route_idx < MAX_ROUTES); 466b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGD("submix_audio_device_release_pipe_l(idx=%d) addr=%s", route_idx, 467b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].address); 468b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rsxadev->routes[route_idx].rsxSink != 0) { 469b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].rsxSink.clear(); 470b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].rsxSink = 0; 471b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 472b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rsxadev->routes[route_idx].rsxSource != 0) { 473b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].rsxSource.clear(); 474b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].rsxSource = 0; 475b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 476b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi memset(rsxadev->routes[route_idx].address, 0, AUDIO_DEVICE_MAX_ADDRESS_LEN); 477b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#ifdef ENABLE_RESAMPLING 478b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi memset(rsxadev->routes[route_idx].resampler_buffer, 0, 479b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sizeof(int16_t) * DEFAULT_PIPE_SIZE_IN_FRAMES); 480b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#endif 4813dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles} 4823dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 4833dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Remove references to the specified input and output streams. When the device no longer 4843dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// references input and output streams destroy the associated pipe. 485b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device 486b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic void submix_audio_device_destroy_pipe_l(struct submix_audio_device * const rsxadev, 4873dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const struct submix_stream_in * const in, 4883dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const struct submix_stream_out * const out) 4893dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles{ 4903dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles MonoPipe* sink; 491b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGV("submix_audio_device_destroy_pipe_l()"); 492b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_idx = -1; 4933dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (in != NULL) { 4943dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN 4953dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const_cast<struct submix_stream_in*>(in)->ref_count--; 496b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi route_idx = in->route_handle; 497b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(rsxadev->routes[route_idx].input == in); 4983dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (in->ref_count == 0) { 499b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].input = NULL; 5003dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 501b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGV("submix_audio_device_destroy_pipe_l(): input ref_count %d", in->ref_count); 5023dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#else 5033dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles rsxadev->input = NULL; 5043dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN 5053dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 506b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (out != NULL) { 507b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi route_idx = out->route_handle; 508b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(rsxadev->routes[route_idx].output == out); 509b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].output = NULL; 510b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 511b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (route_idx != -1 && 512b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].input == NULL && rsxadev->routes[route_idx].output == NULL) { 513b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi submix_audio_device_release_pipe_l(rsxadev, route_idx); 514b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGD("submix_audio_device_destroy_pipe_l(): pipe destroyed"); 5153dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 5163dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles} 5173dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 5187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Sanitize the user specified audio config for a submix input / output stream. 5197072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic void submix_sanitize_config(struct audio_config * const config, const bool is_input_format) 5207072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 5217072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles config->channel_mask = is_input_format ? get_supported_channel_in_mask(config->channel_mask) : 5227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles get_supported_channel_out_mask(config->channel_mask); 5237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles config->sample_rate = get_supported_sample_rate(config->sample_rate); 5247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles config->format = DEFAULT_FORMAT; 5257072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 5267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 5277072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Verify a submix input or output stream can be opened. 528b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device 529b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic bool submix_open_validate_l(const struct submix_audio_device * const rsxadev, 530b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_idx, 5317072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const struct audio_config * const config, 5327072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const bool opening_input) 5337072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{ 5343dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles bool input_open; 5353dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles bool output_open; 5367072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles audio_config pipe_config; 5377072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 5387072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Query the device for the current audio config and whether input and output streams are open. 539b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi output_open = rsxadev->routes[route_idx].output != NULL; 540b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi input_open = rsxadev->routes[route_idx].input != NULL; 541b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi memcpy(&pipe_config, &rsxadev->routes[route_idx].config.common, sizeof(pipe_config)); 5427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 5433dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // If the stream is already open, don't open it again. 5443dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (opening_input ? !ENABLE_LEGACY_INPUT_OPEN && input_open : output_open) { 545b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGE("submix_open_validate_l(): %s stream already open.", opening_input ? "Input" : 5463dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles "Output"); 5473dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles return false; 5483dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 5493dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 550b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi SUBMIX_ALOGV("submix_open_validate_l(): sample rate=%d format=%x " 5513dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles "%s_channel_mask=%x", config->sample_rate, config->format, 5523dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles opening_input ? "in" : "out", config->channel_mask); 5533dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 5543dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // If either stream is open, verify the existing audio config the pipe matches the user 5557072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // specified config. 5563dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (input_open || output_open) { 5577072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const audio_config * const input_config = opening_input ? config : &pipe_config; 5587072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const audio_config * const output_config = opening_input ? &pipe_config : config; 5597072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Get the channel mask of the open device. 5607072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles pipe_config.channel_mask = 561b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi opening_input ? rsxadev->routes[route_idx].config.output_channel_mask : 562b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[route_idx].config.input_channel_mask; 5637072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles if (!audio_config_compare(input_config, output_config)) { 564b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGE("submix_open_validate_l(): Unsupported format."); 5653dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles return false; 5667072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 5677072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 5687072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return true; 5697072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles} 5707072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 571b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device 572b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic status_t submix_get_route_idx_for_address_l(const struct submix_audio_device * const rsxadev, 573b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const char* address, /*in*/ 574b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int *idx /*out*/) 575b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi{ 576b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // Do we already have a route for this address 577b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_idx = -1; 578b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_empty_idx = -1; // index of an empty route slot that can be used if needed 579b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi for (int i=0 ; i < MAX_ROUTES ; i++) { 580b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (strcmp(rsxadev->routes[i].address, "") == 0) { 581b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi route_empty_idx = i; 582b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 583b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (strncmp(rsxadev->routes[i].address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) { 584b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi route_idx = i; 585b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi break; 586b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 587b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 588b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 589b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if ((route_idx == -1) && (route_empty_idx == -1)) { 590b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGE("Cannot create new route for address %s, max number of routes reached", address); 591b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi return -ENOMEM; 592b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 593b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (route_idx == -1) { 594b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi route_idx = route_empty_idx; 595b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 596b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi *idx = route_idx; 597b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi return OK; 598b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi} 599b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 600b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 601e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles// Calculate the maximum size of the pipe buffer in frames for the specified stream. 602e54c12cd532dc36286d500c03ad638402254d4e5Stewart Milesstatic size_t calculate_stream_pipe_size_in_frames(const struct audio_stream *stream, 603e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles const struct submix_config *config, 604c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t pipe_frames, 605c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t stream_frame_size) 606e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles{ 607e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles const size_t pipe_frame_size = config->pipe_frame_size; 608e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles const size_t max_frame_size = max(stream_frame_size, pipe_frame_size); 609e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles return (pipe_frames * config->pipe_frame_size) / max_frame_size; 610e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles} 611e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles 61288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi/* audio HAL functions */ 61388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 61488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t out_get_sample_rate(const struct audio_stream *stream) 61588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 616f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( 617f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const_cast<struct audio_stream *>(stream)); 61802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 619b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const uint32_t out_rate = out->dev->routes[out->route_handle].config.output_sample_rate; 62002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#else 621b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const uint32_t out_rate = out->dev->routes[out->route_handle].config.common.sample_rate; 62202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 623b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi SUBMIX_ALOGV("out_get_sample_rate() returns %u for addr %s", 624b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi out_rate, out->dev->routes[out->route_handle].address); 62588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return out_rate; 62688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 62788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 62888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 62988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 63002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream); 63102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 63202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // The sample rate of the stream can't be changed once it's set since this would change the 63302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // output buffer size and hence break playback to the shared pipe. 634b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rate != out->dev->routes[out->route_handle].config.output_sample_rate) { 635c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent ALOGE("out_set_sample_rate() resampling enabled can't change sample rate from " 636b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi "%u to %u for addr %s", 637b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi out->dev->routes[out->route_handle].config.output_sample_rate, rate, 638b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi out->dev->routes[out->route_handle].address); 63902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles return -ENOSYS; 64002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles } 64102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 6427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles if (!sample_rate_supported(rate)) { 64388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi ALOGE("out_set_sample_rate(rate=%u) rate unsupported", rate); 64488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 64588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 646c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("out_set_sample_rate(rate=%u)", rate); 647b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi out->dev->routes[out->route_handle].config.common.sample_rate = rate; 64888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 64988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 65088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 65188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic size_t out_get_buffer_size(const struct audio_stream *stream) 65288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 653f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( 654f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const_cast<struct audio_stream *>(stream)); 655b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const struct submix_config * const config = &out->dev->routes[out->route_handle].config; 656c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t stream_frame_size = 657c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent audio_stream_out_frame_size((const struct audio_stream_out *)stream); 658e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles const size_t buffer_size_frames = calculate_stream_pipe_size_in_frames( 659c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent stream, config, config->buffer_period_size_frames, stream_frame_size); 660c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t buffer_size_bytes = buffer_size_frames * stream_frame_size; 661568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames", 662e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles buffer_size_bytes, buffer_size_frames); 663e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles return buffer_size_bytes; 66488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 66588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 66688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_channel_mask_t out_get_channels(const struct audio_stream *stream) 66788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 668f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( 669f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const_cast<struct audio_stream *>(stream)); 670b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi uint32_t channel_mask = out->dev->routes[out->route_handle].config.output_channel_mask; 671568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles SUBMIX_ALOGV("out_get_channels() returns %08x", channel_mask); 672568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles return channel_mask; 67388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 67488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 67588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_format_t out_get_format(const struct audio_stream *stream) 67688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 677568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( 678568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles const_cast<struct audio_stream *>(stream)); 679b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const audio_format_t format = out->dev->routes[out->route_handle].config.common.format; 680568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles SUBMIX_ALOGV("out_get_format() returns %x", format); 681568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles return format; 68288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 68388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 68488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_format(struct audio_stream *stream, audio_format_t format) 68588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 686568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream); 687b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (format != out->dev->routes[out->route_handle].config.common.format) { 688c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles ALOGE("out_set_format(format=%x) format unsupported", format); 68988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 69088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 691c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("out_set_format(format=%x)", format); 692c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles return 0; 69388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 69488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 69588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_standby(struct audio_stream *stream) 69688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 697eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi ALOGI("out_standby()"); 698b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream); 699b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_audio_device * const rsxadev = out->dev; 700eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 701f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 702eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 703b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi out->output_standby = true; 7040b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung out->frames_written_since_standby = 0; 705eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 706f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 707eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 70888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 70988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 71088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 71188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_dump(const struct audio_stream *stream, int fd) 71288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 713c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 714c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)fd; 71588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 71688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 71788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 71888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 71988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 720d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi int exiting = -1; 721d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi AudioParameter parms = AudioParameter(String8(kvpairs)); 722c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("out_set_parameters() kvpairs='%s'", kvpairs); 7233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 724d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi // FIXME this is using hard-coded strings but in the future, this functionality will be 725d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi // converted to use audio HAL extensions required to support tunneling 726d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi if ((parms.getInt(String8("exiting"), exiting) == NO_ERROR) && (exiting > 0)) { 727f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct submix_audio_device * const rsxadev = 728f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles audio_stream_get_submix_stream_out(stream)->dev; 729f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 730eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi { // using the sink 731b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sp<MonoPipe> sink = 732b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[audio_stream_get_submix_stream_out(stream)->route_handle] 733b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi .rsxSink; 734f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles if (sink == NULL) { 735f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 736eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi return 0; 737eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi } 738d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi 739793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi ALOGD("out_set_parameters(): shutting down MonoPipe sink"); 740eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi sink->shutdown(true); 741eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi } // done using the sink 742f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 743d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi } 74488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 74588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 74688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 74788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic char * out_get_parameters(const struct audio_stream *stream, const char *keys) 74888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 749c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 750c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)keys; 75188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return strdup(""); 75288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 75388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 75488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t out_get_latency(const struct audio_stream_out *stream) 75588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 756f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out( 757f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const_cast<struct audio_stream_out *>(stream)); 758b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const struct submix_config * const config = &out->dev->routes[out->route_handle].config; 759c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t stream_frame_size = 760c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent audio_stream_out_frame_size(stream); 761e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles const size_t buffer_size_frames = calculate_stream_pipe_size_in_frames( 762c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent &stream->common, config, config->buffer_size_frames, stream_frame_size); 76310f1a806e6537835de7f71dbc05db1889436732eStewart Miles const uint32_t sample_rate = out_get_sample_rate(&stream->common); 76410f1a806e6537835de7f71dbc05db1889436732eStewart Miles const uint32_t latency_ms = (buffer_size_frames * 1000) / sample_rate; 765e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles SUBMIX_ALOGV("out_get_latency() returns %u ms, size in frames %zu, sample rate %u", 76610f1a806e6537835de7f71dbc05db1889436732eStewart Miles latency_ms, buffer_size_frames, sample_rate); 767568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles return latency_ms; 76888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 76988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 77088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_volume(struct audio_stream_out *stream, float left, 77188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi float right) 77288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 773c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 774c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)left; 775c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)right; 77688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 77788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 77888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 77988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 78088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi size_t bytes) 78188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 782c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("out_write(bytes=%zd)", bytes); 783eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi ssize_t written_frames = 0; 784c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t frame_size = audio_stream_out_frame_size(stream); 7853dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream); 7863dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles struct submix_audio_device * const rsxadev = out->dev; 78790b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi const size_t frames = bytes / frame_size; 78890b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi 789f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 79088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 791b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi out->output_standby = false; 792eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 793b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sp<MonoPipe> sink = rsxadev->routes[out->route_handle].rsxSink; 794f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles if (sink != NULL) { 79590b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi if (sink->isShutdown()) { 796eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi sink.clear(); 797f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 798c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("out_write(): pipe shutdown, ignoring the write."); 79990b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi // the pipe has already been shutdown, this buffer will be lost but we must 80090b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi // simulate timing so we don't drain the output faster than realtime 80190b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi usleep(frames * 1000000 / out_get_sample_rate(&stream->common)); 80290b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi return bytes; 80390b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi } 80488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } else { 805f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 80688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi ALOGE("out_write without a pipe!"); 80788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi ALOG_ASSERT("out_write without a pipe!"); 80888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 80988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 81088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 8112d199fe082312963edd1ac198197280a4f18ca21Stewart Miles // If the write to the sink would block when no input stream is present, flush enough frames 8122d199fe082312963edd1ac198197280a4f18ca21Stewart Miles // from the pipe to make space to write the most recent data. 8132d199fe082312963edd1ac198197280a4f18ca21Stewart Miles { 8142d199fe082312963edd1ac198197280a4f18ca21Stewart Miles const size_t availableToWrite = sink->availableToWrite(); 815b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sp<MonoPipeReader> source = rsxadev->routes[out->route_handle].rsxSource; 816b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rsxadev->routes[out->route_handle].input == NULL && availableToWrite < frames) { 8172d199fe082312963edd1ac198197280a4f18ca21Stewart Miles static uint8_t flush_buffer[64]; 8182d199fe082312963edd1ac198197280a4f18ca21Stewart Miles const size_t flushBufferSizeFrames = sizeof(flush_buffer) / frame_size; 8192d199fe082312963edd1ac198197280a4f18ca21Stewart Miles size_t frames_to_flush_from_source = frames - availableToWrite; 8202d199fe082312963edd1ac198197280a4f18ca21Stewart Miles SUBMIX_ALOGV("out_write(): flushing %d frames from the pipe to avoid blocking", 8212d199fe082312963edd1ac198197280a4f18ca21Stewart Miles frames_to_flush_from_source); 8222d199fe082312963edd1ac198197280a4f18ca21Stewart Miles while (frames_to_flush_from_source) { 8232d199fe082312963edd1ac198197280a4f18ca21Stewart Miles const size_t flush_size = min(frames_to_flush_from_source, flushBufferSizeFrames); 8242d199fe082312963edd1ac198197280a4f18ca21Stewart Miles frames_to_flush_from_source -= flush_size; 825b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // read does not block 82604c88495bb7caf851f9802dee20a2a1ffceff195Glenn Kasten source->read(flush_buffer, flush_size); 8272d199fe082312963edd1ac198197280a4f18ca21Stewart Miles } 8282d199fe082312963edd1ac198197280a4f18ca21Stewart Miles } 8292d199fe082312963edd1ac198197280a4f18ca21Stewart Miles } 8302d199fe082312963edd1ac198197280a4f18ca21Stewart Miles 831f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 83288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 833eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi written_frames = sink->write(buffer, frames); 834eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi 83592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 83692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles if (out->log_fd >= 0) write(out->log_fd, buffer, written_frames * frame_size); 83792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 83892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles 839eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi if (written_frames < 0) { 840eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi if (written_frames == (ssize_t)NEGOTIATE) { 84188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi ALOGE("out_write() write to pipe returned NEGOTIATE"); 842eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 843f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 844eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi sink.clear(); 845f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 846eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 847eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi written_frames = 0; 8486acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi return 0; 84988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } else { 85088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi // write() returned UNDERRUN or WOULD_BLOCK, retry 8515685a0845ecde4a1e53684473af3de77e6641af6Colin Cross ALOGE("out_write() write to pipe returned unexpected %zd", written_frames); 852eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi written_frames = sink->write(buffer, frames); 85388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 85488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 85588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 856f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 857eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi sink.clear(); 85825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi if (written_frames > 0) { 8590b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung out->frames_written_since_standby += written_frames; 8600b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung out->frames_written += written_frames; 86125f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi } 862f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 86388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 864eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi if (written_frames < 0) { 8655685a0845ecde4a1e53684473af3de77e6641af6Colin Cross ALOGE("out_write() failed writing to pipe with %zd", written_frames); 866eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi return 0; 86788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 868c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles const ssize_t written_bytes = written_frames * frame_size; 86902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles SUBMIX_ALOGV("out_write() wrote %zd bytes %zd frames", written_bytes, written_frames); 870c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles return written_bytes; 87188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 87288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 87325f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivistatic int out_get_presentation_position(const struct audio_stream_out *stream, 87425f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi uint64_t *frames, struct timespec *timestamp) 87525f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi{ 8760b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung if (stream == NULL || frames == NULL || timestamp == NULL) { 8770b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung return -EINVAL; 8780b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung } 8790b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung 8800b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung const submix_stream_out *out = audio_stream_out_get_submix_stream_out( 8810b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung const_cast<struct audio_stream_out *>(stream)); 88225f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi struct submix_audio_device * const rsxadev = out->dev; 88325f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi 8840b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung int ret = -EWOULDBLOCK; 88525f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi pthread_mutex_lock(&rsxadev->lock); 8860b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung const ssize_t frames_in_pipe = 8870b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung rsxadev->routes[out->route_handle].rsxSource->availableToRead(); 8880b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung if (CC_UNLIKELY(frames_in_pipe < 0)) { 8890b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung *frames = out->frames_written; 8900b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung ret = 0; 8910b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung } else if (out->frames_written >= (uint64_t)frames_in_pipe) { 8920b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung *frames = out->frames_written - frames_in_pipe; 8930b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung ret = 0; 89425f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi } 8950b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung pthread_mutex_unlock(&rsxadev->lock); 8960b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung 8970b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung if (ret == 0) { 89825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi clock_gettime(CLOCK_MONOTONIC, timestamp); 89925f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi } 90025f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi 90125f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi SUBMIX_ALOGV("out_get_presentation_position() got frames=%llu timestamp sec=%llu", 90225f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi frames ? *frames : -1, timestamp ? timestamp->tv_sec : -1); 90325f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi 90425f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi return ret; 90525f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi} 90625f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi 90788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_get_render_position(const struct audio_stream_out *stream, 90888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi uint32_t *dsp_frames) 90988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 9100b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung if (stream == NULL || dsp_frames == NULL) { 91125f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi return -EINVAL; 91225f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi } 9130b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung 9140b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung const submix_stream_out *out = audio_stream_out_get_submix_stream_out( 9150b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung const_cast<struct audio_stream_out *>(stream)); 9160b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung struct submix_audio_device * const rsxadev = out->dev; 9170b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung 9180b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung pthread_mutex_lock(&rsxadev->lock); 9190b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung const ssize_t frames_in_pipe = 9200b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung rsxadev->routes[out->route_handle].rsxSource->availableToRead(); 9210b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung if (CC_UNLIKELY(frames_in_pipe < 0)) { 9220b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung *dsp_frames = (uint32_t)out->frames_written_since_standby; 9230b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung } else { 9240b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung *dsp_frames = out->frames_written_since_standby > (uint64_t) frames_in_pipe ? 9250b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung (uint32_t)(out->frames_written_since_standby - frames_in_pipe) : 0; 92625f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi } 9270b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung pthread_mutex_unlock(&rsxadev->lock); 9280b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung 9290b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung return 0; 93088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 93188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 93288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 93388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 934c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 935c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)effect; 93688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 93788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 93888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 93988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 94088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 941c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 942c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)effect; 94388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 94488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 94588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 94688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_get_next_write_timestamp(const struct audio_stream_out *stream, 94788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi int64_t *timestamp) 94888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 949c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 950c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)timestamp; 95188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -EINVAL; 95288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 95388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 95488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi/** audio_stream_in implementation **/ 95588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t in_get_sample_rate(const struct audio_stream *stream) 95688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 957f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( 958f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const_cast<struct audio_stream*>(stream)); 95902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 960b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const uint32_t rate = in->dev->routes[in->route_handle].config.input_sample_rate; 96102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#else 962b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const uint32_t rate = in->dev->routes[in->route_handle].config.common.sample_rate; 96302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 96402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles SUBMIX_ALOGV("in_get_sample_rate() returns %u", rate); 96502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles return rate; 96688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 96788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 96888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) 96988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 970568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream); 97102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 97202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // The sample rate of the stream can't be changed once it's set since this would change the 97302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // input buffer size and hence break recording from the shared pipe. 974b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rate != in->dev->routes[in->route_handle].config.input_sample_rate) { 975c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent ALOGE("in_set_sample_rate() resampling enabled can't change sample rate from " 976b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi "%u to %u", in->dev->routes[in->route_handle].config.input_sample_rate, rate); 97702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles return -ENOSYS; 97802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles } 97902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 9807072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles if (!sample_rate_supported(rate)) { 9817072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles ALOGE("in_set_sample_rate(rate=%u) rate unsupported", rate); 9827072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return -ENOSYS; 9837072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 984b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->dev->routes[in->route_handle].config.common.sample_rate = rate; 985568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles SUBMIX_ALOGV("in_set_sample_rate() set %u", rate); 986568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles return 0; 98788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 98888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 98988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic size_t in_get_buffer_size(const struct audio_stream *stream) 99088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 991f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( 992f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles const_cast<struct audio_stream*>(stream)); 993b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const struct submix_config * const config = &in->dev->routes[in->route_handle].config; 994c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t stream_frame_size = 995c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent audio_stream_in_frame_size((const struct audio_stream_in *)stream); 99602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles size_t buffer_size_frames = calculate_stream_pipe_size_in_frames( 997c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent stream, config, config->buffer_period_size_frames, stream_frame_size); 99802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 99902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Scale the size of the buffer based upon the maximum number of frames that could be returned 100002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // given the ratio of output to input sample rate. 100102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles buffer_size_frames = (size_t)(((float)buffer_size_frames * 100202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles (float)config->input_sample_rate) / 100302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles (float)config->output_sample_rate); 100402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 1005c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t buffer_size_bytes = buffer_size_frames * stream_frame_size; 1006e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles SUBMIX_ALOGV("in_get_buffer_size() returns %zu bytes, %zu frames", buffer_size_bytes, 1007e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles buffer_size_frames); 1008e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles return buffer_size_bytes; 100988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 101088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 101188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_channel_mask_t in_get_channels(const struct audio_stream *stream) 101288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 10137072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( 10147072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const_cast<struct audio_stream*>(stream)); 1015b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const audio_channel_mask_t channel_mask = 1016b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->dev->routes[in->route_handle].config.input_channel_mask; 10177072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles SUBMIX_ALOGV("in_get_channels() returns %x", channel_mask); 10187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return channel_mask; 101988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 102088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 102188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_format_t in_get_format(const struct audio_stream *stream) 102288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1023568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( 10247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles const_cast<struct audio_stream*>(stream)); 1025b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const audio_format_t format = in->dev->routes[in->route_handle].config.common.format; 1026568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles SUBMIX_ALOGV("in_get_format() returns %x", format); 1027568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles return format; 102888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 102988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 103088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_format(struct audio_stream *stream, audio_format_t format) 103188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1032568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream); 1033b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (format != in->dev->routes[in->route_handle].config.common.format) { 1034c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles ALOGE("in_set_format(format=%x) format unsupported", format); 103588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 103688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 1037c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("in_set_format(format=%x)", format); 1038c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles return 0; 103988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 104088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 104188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_standby(struct audio_stream *stream) 104288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1043eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi ALOGI("in_standby()"); 1044b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream); 1045b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_audio_device * const rsxadev = in->dev; 1046eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1047f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 1048eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1049b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->input_standby = true; 1050eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1051f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 1052eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 105388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 105488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 105588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 105688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_dump(const struct audio_stream *stream, int fd) 105788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1058c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 1059c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)fd; 106088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 106188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 106288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 106388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_parameters(struct audio_stream *stream, const char *kvpairs) 106488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1065c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 1066c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)kvpairs; 106788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 106888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 106988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 107088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic char * in_get_parameters(const struct audio_stream *stream, 107188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi const char *keys) 107288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1073c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 1074c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)keys; 107588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return strdup(""); 107688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 107788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 107888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_gain(struct audio_stream_in *stream, float gain) 107988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1080c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 1081c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)gain; 108288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 108388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 108488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 108588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic ssize_t in_read(struct audio_stream_in *stream, void* buffer, 108688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi size_t bytes) 108788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1088f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream); 1089f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct submix_audio_device * const rsxadev = in->dev; 1090e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles struct audio_config *format; 1091c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent const size_t frame_size = audio_stream_in_frame_size(stream); 1092eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi const size_t frames_to_read = bytes / frame_size; 109388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1094c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("in_read bytes=%zu", bytes); 1095f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 109688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1097257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi const bool output_standby = rsxadev->routes[in->route_handle].output == NULL 1098257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi ? true : rsxadev->routes[in->route_handle].output->output_standby; 1099257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi const bool output_standby_transition = (in->output_standby_rec_thr != output_standby); 1100257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi in->output_standby_rec_thr = output_standby; 1101eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1102b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (in->input_standby || output_standby_transition) { 1103b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->input_standby = false; 1104eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // keep track of when we exit input standby (== first read == start "real recording") 1105eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // or when we start recording silence, and reset projected time 1106eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi int rc = clock_gettime(CLOCK_MONOTONIC, &in->record_start_time); 1107eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi if (rc == 0) { 1108eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi in->read_counter_frames = 0; 1109eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi } 1110eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi } 1111eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1112eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi in->read_counter_frames += frames_to_read; 1113eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi size_t remaining_frames = frames_to_read; 1114eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1115eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi { 1116eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi // about to read from audio source 1117b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sp<MonoPipeReader> source = rsxadev->routes[in->route_handle].rsxSource; 1118f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles if (source == NULL) { 1119793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi in->read_error_count++;// ok if it rolls over 1120793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi ALOGE_IF(in->read_error_count < MAX_READ_ERROR_LOGS, 1121793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi "no audio pipe yet we're trying to read! (not all errors will be logged)"); 1122f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 11233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles usleep(frames_to_read * 1000000 / in_get_sample_rate(&stream->common)); 1124eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi memset(buffer, 0, bytes); 1125eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi return bytes; 1126eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi } 112788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1128f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 112988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1130eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi // read the data from the pipe (it's non blocking) 1131eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi int attempts = 0; 1132eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi char* buff = (char*)buffer; 1133e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if ENABLE_CHANNEL_CONVERSION 1134e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // Determine whether channel conversion is required. 1135dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent const uint32_t input_channels = audio_channel_count_from_in_mask( 1136b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[in->route_handle].config.input_channel_mask); 1137dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent const uint32_t output_channels = audio_channel_count_from_out_mask( 1138b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[in->route_handle].config.output_channel_mask); 1139e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles if (input_channels != output_channels) { 1140e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles SUBMIX_ALOGV("in_read(): %d output channels will be converted to %d " 1141e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles "input channels", output_channels, input_channels); 1142e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // Only support 16-bit PCM channel conversion from mono to stereo or stereo to mono. 1143b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(rsxadev->routes[in->route_handle].config.common.format == 1144b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi AUDIO_FORMAT_PCM_16_BIT); 1145e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles ALOG_ASSERT((input_channels == 1 && output_channels == 2) || 1146e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles (input_channels == 2 && output_channels == 1)); 1147e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles } 1148e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // ENABLE_CHANNEL_CONVERSION 1149e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles 115002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 115102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles const uint32_t input_sample_rate = in_get_sample_rate(&stream->common); 1152b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const uint32_t output_sample_rate = 1153b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[in->route_handle].config.output_sample_rate; 115402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles const size_t resampler_buffer_size_frames = 1155b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sizeof(rsxadev->routes[in->route_handle].resampler_buffer) / 1156b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sizeof(rsxadev->routes[in->route_handle].resampler_buffer[0]); 115702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles float resampler_ratio = 1.0f; 115802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Determine whether resampling is required. 115902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles if (input_sample_rate != output_sample_rate) { 116002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles resampler_ratio = (float)output_sample_rate / (float)input_sample_rate; 116102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Only support 16-bit PCM mono resampling. 116202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // NOTE: Resampling is performed after the channel conversion step. 1163b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(rsxadev->routes[in->route_handle].config.common.format == 1164b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi AUDIO_FORMAT_PCM_16_BIT); 1165b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOG_ASSERT(audio_channel_count_from_in_mask( 1166b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[in->route_handle].config.input_channel_mask) == 1); 116702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles } 116802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 116902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles 1170eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi while ((remaining_frames > 0) && (attempts < MAX_READ_ATTEMPTS)) { 117102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles ssize_t frames_read = -1977; 1172e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles size_t read_frames = remaining_frames; 117302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 117402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles char* const saved_buff = buff; 117502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles if (resampler_ratio != 1.0f) { 117602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Calculate the number of frames from the pipe that need to be read to generate 117702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // the data for the input stream read. 117802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles const size_t frames_required_for_resampler = (size_t)( 117902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles (float)read_frames * (float)resampler_ratio); 118002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles read_frames = min(frames_required_for_resampler, resampler_buffer_size_frames); 118102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Read into the resampler buffer. 1182b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi buff = (char*)rsxadev->routes[in->route_handle].resampler_buffer; 118302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles } 118402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 1185e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if ENABLE_CHANNEL_CONVERSION 1186e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles if (output_channels == 1 && input_channels == 2) { 1187e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // Need to read half the requested frames since the converted output 1188e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // data will take twice the space (mono->stereo). 1189e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles read_frames /= 2; 1190e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles } 1191e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // ENABLE_CHANNEL_CONVERSION 1192e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles 1193e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles SUBMIX_ALOGV("in_read(): frames available to read %zd", source->availableToRead()); 1194e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles 119504c88495bb7caf851f9802dee20a2a1ffceff195Glenn Kasten frames_read = source->read(buff, read_frames); 1196e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles 1197e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles SUBMIX_ALOGV("in_read(): frames read %zd", frames_read); 1198e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles 1199e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if ENABLE_CHANNEL_CONVERSION 1200e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // Perform in-place channel conversion. 1201e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // NOTE: In the following "input stream" refers to the data returned by this function 1202e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // and "output stream" refers to the data read from the pipe. 1203e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles if (input_channels != output_channels && frames_read > 0) { 1204e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles int16_t *data = (int16_t*)buff; 1205e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles if (output_channels == 2 && input_channels == 1) { 1206e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // Offset into the output stream data in samples. 1207e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles ssize_t output_stream_offset = 0; 1208e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles for (ssize_t input_stream_frame = 0; input_stream_frame < frames_read; 1209e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles input_stream_frame++, output_stream_offset += 2) { 1210e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // Average the content from both channels. 1211e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles data[input_stream_frame] = ((int32_t)data[output_stream_offset] + 1212e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles (int32_t)data[output_stream_offset + 1]) / 2; 1213e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles } 1214e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles } else if (output_channels == 1 && input_channels == 2) { 1215e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles // Offset into the input stream data in samples. 1216e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles ssize_t input_stream_offset = (frames_read - 1) * 2; 1217e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles for (ssize_t output_stream_frame = frames_read - 1; output_stream_frame >= 0; 1218e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles output_stream_frame--, input_stream_offset -= 2) { 1219e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles const short sample = data[output_stream_frame]; 1220e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles data[input_stream_offset] = sample; 1221e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles data[input_stream_offset + 1] = sample; 1222e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles } 1223e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles } 1224e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles } 1225e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // ENABLE_CHANNEL_CONVERSION 12263dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 122702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING 122802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles if (resampler_ratio != 1.0f) { 122902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles SUBMIX_ALOGV("in_read(): resampling %zd frames", frames_read); 123002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles const int16_t * const data = (int16_t*)buff; 123102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles int16_t * const resampled_buffer = (int16_t*)saved_buff; 123202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // Resample with *no* filtering - if the data from the ouptut stream was really 123302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles // sampled at a different rate this will result in very nasty aliasing. 123402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles const float output_stream_frames = (float)frames_read; 123502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles size_t input_stream_frame = 0; 123602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles for (float output_stream_frame = 0.0f; 123702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles output_stream_frame < output_stream_frames && 123802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles input_stream_frame < remaining_frames; 123902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles output_stream_frame += resampler_ratio, input_stream_frame++) { 124002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles resampled_buffer[input_stream_frame] = data[(size_t)output_stream_frame]; 124102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles } 124202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles ALOG_ASSERT(input_stream_frame <= (ssize_t)resampler_buffer_size_frames); 124302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles SUBMIX_ALOGV("in_read(): resampler produced %zd frames", input_stream_frame); 124402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles frames_read = input_stream_frame; 124502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles buff = saved_buff; 124602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles } 124702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING 124802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles 1249eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi if (frames_read > 0) { 125092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 125192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles if (in->log_fd >= 0) write(in->log_fd, buff, frames_read * frame_size); 125292854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 125392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles 1254eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi remaining_frames -= frames_read; 1255eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi buff += frames_read * frame_size; 1256c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV(" in_read (att=%d) got %zd frames, remaining=%zu", 1257c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles attempts, frames_read, remaining_frames); 1258eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi } else { 12593dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles attempts++; 1260c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGE(" in_read read returned %zd", frames_read); 1261eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi usleep(READ_ATTEMPT_SLEEP_MS * 1000); 1262eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi } 126388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 1264eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi // done using the source 1265f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_lock(&rsxadev->lock); 1266eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi source.clear(); 1267f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles pthread_mutex_unlock(&rsxadev->lock); 126888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 126988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 12706acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi if (remaining_frames > 0) { 12713dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles const size_t remaining_bytes = remaining_frames * frame_size; 127210f1a806e6537835de7f71dbc05db1889436732eStewart Miles SUBMIX_ALOGV(" clearing remaining_frames = %zu", remaining_frames); 12733dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles memset(((char*)buffer)+ bytes - remaining_bytes, 0, remaining_bytes); 12746acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi } 127588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1276eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // compute how much we need to sleep after reading the data by comparing the wall clock with 1277eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // the projected time at which we should return. 1278eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi struct timespec time_after_read;// wall clock after reading from the pipe 1279eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi struct timespec record_duration;// observed record duration 1280eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi int rc = clock_gettime(CLOCK_MONOTONIC, &time_after_read); 1281eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi const uint32_t sample_rate = in_get_sample_rate(&stream->common); 1282eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi if (rc == 0) { 1283eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi // for how long have we been recording? 1284eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi record_duration.tv_sec = time_after_read.tv_sec - in->record_start_time.tv_sec; 1285eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi record_duration.tv_nsec = time_after_read.tv_nsec - in->record_start_time.tv_nsec; 1286eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi if (record_duration.tv_nsec < 0) { 1287eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi record_duration.tv_sec--; 1288eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi record_duration.tv_nsec += 1000000000; 1289eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi } 1290eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1291f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles // read_counter_frames contains the number of frames that have been read since the 1292f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles // beginning of recording (including this call): it's converted to usec and compared to 1293f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles // how long we've been recording for, which gives us how long we must wait to sync the 1294f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles // projected recording time, and the observed recording time. 1295eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi long projected_vs_observed_offset_us = 1296eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi ((int64_t)(in->read_counter_frames 1297eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi - (record_duration.tv_sec*sample_rate))) 1298eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi * 1000000 / sample_rate 1299eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi - (record_duration.tv_nsec / 1000); 1300eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1301c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV(" record duration %5lds %3ldms, will wait: %7ldus", 1302eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi record_duration.tv_sec, record_duration.tv_nsec/1000000, 1303eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi projected_vs_observed_offset_us); 1304eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi if (projected_vs_observed_offset_us > 0) { 1305eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi usleep(projected_vs_observed_offset_us); 1306eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi } 130788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi } 1308eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 1309c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles SUBMIX_ALOGV("in_read returns %zu", bytes); 1310eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi return bytes; 1311eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 131288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 131388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 131488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) 131588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1316c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 131788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 131888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 131988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 132088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 132188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1322c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 1323c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)effect; 132488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 132588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 132688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 132788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 132888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1329c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)stream; 1330c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)effect; 133188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 133288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 133388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 133488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_open_output_stream(struct audio_hw_device *dev, 133588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi audio_io_handle_t handle, 133688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi audio_devices_t devices, 133788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi audio_output_flags_t flags, 133888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct audio_config *config, 1339f5e2469c02825f018df6336125882812003b8e64Eric Laurent struct audio_stream_out **stream_out, 1340b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const char *address) 134188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1342f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev); 1343b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGD("adev_open_output_stream(address=%s)", address); 134488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct submix_stream_out *out; 134510f1a806e6537835de7f71dbc05db1889436732eStewart Miles bool force_pipe_creation = false; 1346c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)handle; 1347c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)devices; 1348c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)flags; 134988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 13503dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles *stream_out = NULL; 13513dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 13527072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Make sure it's possible to open the device given the current audio config. 13537072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles submix_sanitize_config(config, false); 1354b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1355b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_idx = -1; 1356b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1357b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_lock(&rsxadev->lock); 1358b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1359b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi status_t res = submix_get_route_idx_for_address_l(rsxadev, address, &route_idx); 1360b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (res != OK) { 1361b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGE("Error %d looking for address=%s in adev_open_output_stream", res, address); 1362b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 1363b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi return res; 1364b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 1365b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1366b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (!submix_open_validate_l(rsxadev, route_idx, config, false)) { 1367b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGE("adev_open_output_stream(): Unable to open output stream for address %s", address); 1368b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 13697072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return -EINVAL; 13707072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 13717072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 137288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out = (struct submix_stream_out *)calloc(1, sizeof(struct submix_stream_out)); 1373b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (!out) { 1374b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 1375b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi return -ENOMEM; 1376b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 137788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1378568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles // Initialize the function pointer tables (v-tables). 137988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.get_sample_rate = out_get_sample_rate; 138088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.set_sample_rate = out_set_sample_rate; 138188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.get_buffer_size = out_get_buffer_size; 138288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.get_channels = out_get_channels; 138388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.get_format = out_get_format; 138488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.set_format = out_set_format; 138588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.standby = out_standby; 138688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.dump = out_dump; 138788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.set_parameters = out_set_parameters; 138888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.get_parameters = out_get_parameters; 138988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.add_audio_effect = out_add_audio_effect; 139088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.common.remove_audio_effect = out_remove_audio_effect; 139188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.get_latency = out_get_latency; 139288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.set_volume = out_set_volume; 139388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.write = out_write; 139488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.get_render_position = out_get_render_position; 139588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi out->stream.get_next_write_timestamp = out_get_next_write_timestamp; 139625f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi out->stream.get_presentation_position = out_get_presentation_position; 139725f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi 139810f1a806e6537835de7f71dbc05db1889436732eStewart Miles#if ENABLE_RESAMPLING 139910f1a806e6537835de7f71dbc05db1889436732eStewart Miles // Recreate the pipe with the correct sample rate so that MonoPipe.write() rate limits 140010f1a806e6537835de7f71dbc05db1889436732eStewart Miles // writes correctly. 1401b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi force_pipe_creation = rsxadev->routes[route_idx].config.common.sample_rate 1402b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi != config->sample_rate; 140310f1a806e6537835de7f71dbc05db1889436732eStewart Miles#endif // ENABLE_RESAMPLING 140410f1a806e6537835de7f71dbc05db1889436732eStewart Miles 140510f1a806e6537835de7f71dbc05db1889436732eStewart Miles // If the sink has been shutdown or pipe recreation is forced (see above), delete the pipe so 140610f1a806e6537835de7f71dbc05db1889436732eStewart Miles // that it's recreated. 1407b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if ((rsxadev->routes[route_idx].rsxSink != NULL 1408b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi && rsxadev->routes[route_idx].rsxSink->isShutdown()) || force_pipe_creation) { 1409b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi submix_audio_device_release_pipe_l(rsxadev, route_idx); 14103dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 141188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1412568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles // Store a pointer to the device from the output stream. 1413568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles out->dev = rsxadev; 14143dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Initialize the pipe. 1415b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGV("adev_open_output_stream(): about to create pipe at index %d", route_idx); 1416b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi submix_audio_device_create_pipe_l(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES, 1417b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi DEFAULT_PIPE_PERIOD_COUNT, NULL, out, address, route_idx); 141892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 141992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles out->log_fd = open(LOG_STREAM_OUT_FILENAME, O_CREAT | O_TRUNC | O_WRONLY, 142092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles LOG_STREAM_FILE_PERMISSIONS); 142192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles ALOGE_IF(out->log_fd < 0, "adev_open_output_stream(): log file open failed %s", 142292854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles strerror(errno)); 142392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles ALOGV("adev_open_output_stream(): log_fd = %d", out->log_fd); 142492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 1425568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles // Return the output stream. 142688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi *stream_out = &out->stream; 142788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1428b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 142988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 143088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 143188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 143288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic void adev_close_output_stream(struct audio_hw_device *dev, 143388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct audio_stream_out *stream) 143488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1435b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_audio_device * rsxadev = audio_hw_device_get_submix_audio_device( 1436b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const_cast<struct audio_hw_device*>(dev)); 14373dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream); 1438b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1439b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_lock(&rsxadev->lock); 1440b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGD("adev_close_output_stream() addr = %s", rsxadev->routes[out->route_handle].address); 1441b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi submix_audio_device_destroy_pipe_l(audio_hw_device_get_submix_audio_device(dev), NULL, out); 144292854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 144392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles if (out->log_fd >= 0) close(out->log_fd); 144492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 1445b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1446b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 14473dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles free(out); 144888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 144988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 145088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 145188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1452c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1453c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)kvpairs; 145488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 145588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 145688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 145788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic char * adev_get_parameters(const struct audio_hw_device *dev, 145888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi const char *keys) 145988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1460c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1461c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)keys; 146288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return strdup("");; 146388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 146488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 146588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_init_check(const struct audio_hw_device *dev) 146688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 146788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi ALOGI("adev_init_check()"); 1468c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 146988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 147088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 147188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 147288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 147388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1474c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1475c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)volume; 147688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 147788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 147888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 147988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_master_volume(struct audio_hw_device *dev, float volume) 148088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1481c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1482c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)volume; 148388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 148488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 148588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 148688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_get_master_volume(struct audio_hw_device *dev, float *volume) 148788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1488c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1489c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)volume; 149088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 149188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 149288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 149388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_master_mute(struct audio_hw_device *dev, bool muted) 149488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1495c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1496c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)muted; 149788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 149888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 149988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 150088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_get_master_mute(struct audio_hw_device *dev, bool *muted) 150188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1502c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1503c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)muted; 150488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 150588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 150688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 150788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 150888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1509c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1510c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)mode; 151188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 151288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 151388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 151488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 151588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1516c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1517c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)state; 151888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 151988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 152088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 152188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 152288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1523c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)dev; 1524c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)state; 152588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOSYS; 152688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 152788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 152888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 152988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi const struct audio_config *config) 153088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1531568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles if (audio_is_linear_pcm(config->format)) { 1532b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi size_t max_buffer_period_size_frames = 0; 1533b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_audio_device * rsxadev = audio_hw_device_get_submix_audio_device( 1534b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const_cast<struct audio_hw_device*>(dev)); 1535b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // look for the largest buffer period size 1536b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi for (int i = 0 ; i < MAX_ROUTES ; i++) { 1537b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rsxadev->routes[i].config.buffer_period_size_frames > max_buffer_period_size_frames) 1538b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi { 1539b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi max_buffer_period_size_frames = rsxadev->routes[i].config.buffer_period_size_frames; 1540b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 1541b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 1542dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent const size_t frame_size_in_bytes = audio_channel_count_from_in_mask(config->channel_mask) * 1543568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles audio_bytes_per_sample(config->format); 1544b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const size_t buffer_size = max_buffer_period_size_frames * frame_size_in_bytes; 154510f1a806e6537835de7f71dbc05db1889436732eStewart Miles SUBMIX_ALOGV("adev_get_input_buffer_size() returns %zu bytes, %zu frames", 1546568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles buffer_size, buffer_period_size_frames); 1547568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles return buffer_size; 1548568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles } 1549568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles return 0; 155088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 155188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 155288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_open_input_stream(struct audio_hw_device *dev, 155388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi audio_io_handle_t handle, 155488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi audio_devices_t devices, 155588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct audio_config *config, 15567d973adff4c9b344b530dd7c585f789d02c605daGlenn Kasten struct audio_stream_in **stream_in, 1557f5e2469c02825f018df6336125882812003b8e64Eric Laurent audio_input_flags_t flags __unused, 1558b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const char *address, 1559f5e2469c02825f018df6336125882812003b8e64Eric Laurent audio_source_t source __unused) 156088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1561f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev); 156288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct submix_stream_in *in; 1563b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi ALOGD("adev_open_input_stream(addr=%s)", address); 1564c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)handle; 1565c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles (void)devices; 156688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 15673dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles *stream_in = NULL; 15683dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 1569b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi // Do we already have a route for this address 1570b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int route_idx = -1; 1571b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1572b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_lock(&rsxadev->lock); 1573b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1574b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi status_t res = submix_get_route_idx_for_address_l(rsxadev, address, &route_idx); 1575b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (res != OK) { 157679fbccf91be4d98d0e04dd840f1ccf156fab2ae3Jean-Michel Trivi ALOGE("Error %d looking for address=%s in adev_open_input_stream", res, address); 1577b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 1578b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi return res; 1579b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 1580b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 15817072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles // Make sure it's possible to open the device given the current audio config. 15827072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles submix_sanitize_config(config, true); 1583b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (!submix_open_validate_l(rsxadev, route_idx, config, true)) { 15847072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles ALOGE("adev_open_input_stream(): Unable to open input stream."); 1585b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 15867072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles return -EINVAL; 15877072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles } 15887072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles 15893dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN 1590b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in = rsxadev->routes[route_idx].input; 15913dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (in) { 15923dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->ref_count++; 1593b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi sp<MonoPipe> sink = rsxadev->routes[route_idx].rsxSink; 15943dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles ALOG_ASSERT(sink != NULL); 15953dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // If the sink has been shutdown, delete the pipe. 1596793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi if (sink != NULL) { 1597793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi if (sink->isShutdown()) { 1598793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi ALOGD(" Non-NULL shut down sink when opening input stream, releasing, refcount=%d", 1599793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi in->ref_count); 1600b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi submix_audio_device_release_pipe_l(rsxadev, in->route_handle); 1601793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi } else { 1602793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi ALOGD(" Non-NULL sink when opening input stream, refcount=%d", in->ref_count); 1603793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi } 1604793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi } else { 1605793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi ALOGE("NULL sink when opening input stream, refcount=%d", in->ref_count); 1606793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi } 16073dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 16083dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#else 16093dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in = NULL; 16103dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN 161188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 16123dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (!in) { 16133dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in = (struct submix_stream_in *)calloc(1, sizeof(struct submix_stream_in)); 16143dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (!in) return -ENOMEM; 16153dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->ref_count = 1; 16163dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles 16173dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Initialize the function pointer tables (v-tables). 16183dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.get_sample_rate = in_get_sample_rate; 16193dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.set_sample_rate = in_set_sample_rate; 16203dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.get_buffer_size = in_get_buffer_size; 16213dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.get_channels = in_get_channels; 16223dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.get_format = in_get_format; 16233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.set_format = in_set_format; 16243dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.standby = in_standby; 16253dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.dump = in_dump; 16263dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.set_parameters = in_set_parameters; 16273dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.get_parameters = in_get_parameters; 16283dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.add_audio_effect = in_add_audio_effect; 16293dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.common.remove_audio_effect = in_remove_audio_effect; 16303dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.set_gain = in_set_gain; 16313dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.read = in_read; 16323dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles in->stream.get_input_frames_lost = in_get_input_frames_lost; 1633b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1634b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->dev = rsxadev; 1635b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#if LOG_STREAMS_TO_FILES 1636b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->log_fd = -1; 1637b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#endif 16383dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles } 163988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1640568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles // Initialize the input stream. 1641eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi in->read_counter_frames = 0; 1642b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->input_standby = true; 1643b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (rsxadev->routes[route_idx].output != NULL) { 1644b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->output_standby_rec_thr = rsxadev->routes[route_idx].output->output_standby; 1645b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } else { 1646b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi in->output_standby_rec_thr = true; 1647b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 1648b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1649793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi in->read_error_count = 0; 16503dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Initialize the pipe. 1651793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi ALOGV("adev_open_input_stream(): about to create pipe"); 1652b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi submix_audio_device_create_pipe_l(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES, 1653b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi DEFAULT_PIPE_PERIOD_COUNT, in, NULL, address, route_idx); 165492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 1655b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi if (in->log_fd >= 0) close(in->log_fd); 165692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles in->log_fd = open(LOG_STREAM_IN_FILENAME, O_CREAT | O_TRUNC | O_WRONLY, 165792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles LOG_STREAM_FILE_PERMISSIONS); 165892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles ALOGE_IF(in->log_fd < 0, "adev_open_input_stream(): log file open failed %s", 165992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles strerror(errno)); 166092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles ALOGV("adev_open_input_stream(): log_fd = %d", in->log_fd); 166192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 16623dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles // Return the input stream. 16633dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles *stream_in = &in->stream; 166488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1665b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 166688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 166788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 166888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 166988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic void adev_close_input_stream(struct audio_hw_device *dev, 1670c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles struct audio_stream_in *stream) 167188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1672b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev); 1673b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 16743dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream); 1675793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi ALOGD("adev_close_input_stream()"); 1676b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_lock(&rsxadev->lock); 1677b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi submix_audio_device_destroy_pipe_l(rsxadev, in, NULL); 167892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES 167992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles if (in->log_fd >= 0) close(in->log_fd); 168092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES 16813dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN 16823dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles if (in->ref_count == 0) free(in); 16833dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#else 16843dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles free(in); 16853dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN 1686b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi 1687b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi pthread_mutex_unlock(&rsxadev->lock); 168888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 168988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 169088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_dump(const audio_hw_device_t *device, int fd) 169188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 1692b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi const struct submix_audio_device * rsxadev = //audio_hw_device_get_submix_audio_device(device); 1693b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi reinterpret_cast<const struct submix_audio_device *>( 1694b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi reinterpret_cast<const uint8_t *>(device) - 1695b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi offsetof(struct submix_audio_device, device)); 1696b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi char msg[100]; 1697b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi int n = sprintf(msg, "\nReroute submix audio module:\n"); 1698b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi write(fd, &msg, n); 1699b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi for (int i=0 ; i < MAX_ROUTES ; i++) { 1700b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi n = sprintf(msg, " route[%d] rate in=%d out=%d, addr=[%s]\n", i, 1701b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[i].config.input_sample_rate, 1702b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[i].config.output_sample_rate, 1703b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi rsxadev->routes[i].address); 1704b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi write(fd, &msg, n); 1705b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 170688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 170788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 170888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 170988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_close(hw_device_t *device) 171088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 171188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi ALOGI("adev_close()"); 171288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi free(device); 171388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 171488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 171588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 171688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_open(const hw_module_t* module, const char* name, 171788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi hw_device_t** device) 171888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{ 171988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi ALOGI("adev_open(name=%s)", name); 172088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi struct submix_audio_device *rsxadev; 172188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 172288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 172388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -EINVAL; 172488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 172588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev = (submix_audio_device*) calloc(1, sizeof(struct submix_audio_device)); 172688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi if (!rsxadev) 172788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return -ENOMEM; 172888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 172988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.common.tag = HARDWARE_DEVICE_TAG; 17305d85c537fcae931428ba8b7a47fdd393cc3cbd88Eric Laurent rsxadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0; 173188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.common.module = (struct hw_module_t *) module; 173288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.common.close = adev_close; 173388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 173488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.init_check = adev_init_check; 173588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.set_voice_volume = adev_set_voice_volume; 173688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.set_master_volume = adev_set_master_volume; 173788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.get_master_volume = adev_get_master_volume; 173888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.set_master_mute = adev_set_master_mute; 173988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.get_master_mute = adev_get_master_mute; 174088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.set_mode = adev_set_mode; 174188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.set_mic_mute = adev_set_mic_mute; 174288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.get_mic_mute = adev_get_mic_mute; 174388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.set_parameters = adev_set_parameters; 174488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.get_parameters = adev_get_parameters; 174588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.get_input_buffer_size = adev_get_input_buffer_size; 174688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.open_output_stream = adev_open_output_stream; 174788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.close_output_stream = adev_close_output_stream; 174888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.open_input_stream = adev_open_input_stream; 174988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.close_input_stream = adev_close_input_stream; 175088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi rsxadev->device.dump = adev_dump; 175188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 1752b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi for (int i=0 ; i < MAX_ROUTES ; i++) { 1753b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi memset(&rsxadev->routes[i], 0, sizeof(route_config)); 1754b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi strcpy(rsxadev->routes[i].address, ""); 1755b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi } 1756eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi 175788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi *device = &rsxadev->device.common; 175888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 175988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi return 0; 176088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} 176188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 176288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic struct hw_module_methods_t hal_module_methods = { 176388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* open */ adev_open, 176488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}; 176588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 176688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct audio_module HAL_MODULE_INFO_SYM = { 176788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* common */ { 176888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* tag */ HARDWARE_MODULE_TAG, 176988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* module_api_version */ AUDIO_MODULE_API_VERSION_0_1, 177088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* hal_api_version */ HARDWARE_HAL_API_VERSION, 177188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* id */ AUDIO_HARDWARE_MODULE_ID, 177288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* name */ "Wifi Display audio HAL", 177388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* author */ "The Android Open Source Project", 177488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* methods */ &hal_module_methods, 177588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* dso */ NULL, 177688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi /* reserved */ { 0 }, 177788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi }, 177888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}; 177988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 178088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} //namespace android 178188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi 178288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} //extern "C" 1783