Support MONO and STERO USB inputs. Allow "dynamic" flag in audio_policy.conf.
Bug 17526569 Change-Id: I64b00fd338eb937303b41608728a18341ee78820
This commit is contained in:
parent
253def9fa0
commit
2cfd81bae0
2 changed files with 34 additions and 46 deletions
|
@ -275,28 +275,19 @@ static unsigned profile_enum_sample_formats(alsa_device_profile* profile, struct
|
|||
|
||||
static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min, unsigned max)
|
||||
{
|
||||
// TODO: Don't return MONO even if the device supports it. This causes problems
|
||||
// in AudioPolicyManager. Revisit.
|
||||
static const unsigned std_out_channel_counts[] = {8, 4, 2/*, 1*/};
|
||||
static const unsigned std_in_channel_counts[] = {8, 4, 2, 1};
|
||||
|
||||
unsigned * channel_counts =
|
||||
profile->direction == PCM_OUT ? std_out_channel_counts : std_in_channel_counts;
|
||||
unsigned num_channel_counts =
|
||||
profile->direction == PCM_OUT
|
||||
? ARRAY_SIZE(std_out_channel_counts) : ARRAY_SIZE(std_in_channel_counts);
|
||||
static const unsigned std_channel_counts[] = {8, 4, 2, 1};
|
||||
|
||||
unsigned num_counts = 0;
|
||||
unsigned index;
|
||||
/* TODO write a profile_test_channel_count() */
|
||||
/* Ensure there is at least one invalid channel count to terminate the channel counts array */
|
||||
for (index = 0; index < num_channel_counts &&
|
||||
for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
|
||||
num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
|
||||
index++) {
|
||||
/* TODO Do we want a channel counts test? */
|
||||
if (channel_counts[index] >= min && channel_counts[index] <= max /* &&
|
||||
if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* &&
|
||||
profile_test_channel_count(profile, channel_counts[index])*/) {
|
||||
profile->channel_counts[num_counts++] = channel_counts[index];
|
||||
profile->channel_counts[num_counts++] = std_channel_counts[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,6 +450,7 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile)
|
|||
};
|
||||
|
||||
const bool isOutProfile = profile->direction == PCM_OUT;
|
||||
|
||||
const char * const * const names_array = isOutProfile ? out_chans_strs : in_chans_strs;
|
||||
const size_t names_size = isOutProfile ? ARRAY_SIZE(out_chans_strs)
|
||||
: ARRAY_SIZE(in_chans_strs);
|
||||
|
@ -467,12 +459,17 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile)
|
|||
buffer[0] = '\0';
|
||||
const int buffer_size = ARRAY_SIZE(buffer);
|
||||
int num_entries = 0;
|
||||
bool stereo_allowed = false;
|
||||
/* We currently support MONO and STEREO, and always report STEREO but some (many)
|
||||
* USB Audio Devices may only announce support for MONO (a headset mic for example), or
|
||||
* The total number of output channels. SO, if the device itself doesn't explicitly
|
||||
* support STEREO, append to the channel config strings we are generating.
|
||||
*/
|
||||
bool stereo_present = false;
|
||||
unsigned index;
|
||||
unsigned channel_count;
|
||||
|
||||
for (index = 0; (channel_count = profile->channel_counts[index]) != 0; index++) {
|
||||
stereo_allowed = stereo_allowed || channel_count == 2;
|
||||
stereo_present = stereo_present || channel_count == 2;
|
||||
if (channel_count < names_size && names_array[channel_count] != NULL) {
|
||||
if (num_entries++ != 0) {
|
||||
strncat(buffer, "|", buffer_size);
|
||||
|
@ -480,14 +477,16 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile)
|
|||
strncat(buffer, names_array[channel_count], buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* emulated modes:
|
||||
* always expose stereo as we can emulate it for PCM_OUT
|
||||
*/
|
||||
if (!stereo_allowed && isOutProfile) {
|
||||
if (!stereo_present) {
|
||||
if (num_entries++ != 0) {
|
||||
strncat(buffer, "|", buffer_size);
|
||||
}
|
||||
strncat(buffer, names_array[2], buffer_size); /* stereo */
|
||||
}
|
||||
|
||||
return strdup(buffer);
|
||||
}
|
||||
|
|
|
@ -104,9 +104,11 @@ struct stream_in {
|
|||
alsa_device_profile * profile;
|
||||
alsa_device_proxy proxy; /* state of the stream */
|
||||
|
||||
// not used?
|
||||
// struct audio_config hal_pcm_config;
|
||||
|
||||
unsigned hal_channel_count; /* channel count exposed to AudioFlinger.
|
||||
* This may differ from the device channel count when
|
||||
* the device is not compatible with AudioFlinger
|
||||
* capabilities, e.g. exposes too many channels or
|
||||
* too few channels. */
|
||||
/* We may need to read more data from the device in order to data reduce to 16bit, 4chan */
|
||||
void * conversion_buffer; /* any conversions are put into here
|
||||
* they could come from here too if
|
||||
|
@ -623,25 +625,13 @@ static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
|
|||
static size_t in_get_buffer_size(const struct audio_stream *stream)
|
||||
{
|
||||
const struct stream_in * in = ((const struct stream_in*)stream);
|
||||
size_t buffer_size =
|
||||
proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream));
|
||||
ALOGV("in_get_buffer_size() = %zd", buffer_size);
|
||||
|
||||
return buffer_size;
|
||||
return proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream));
|
||||
}
|
||||
|
||||
static uint32_t in_get_channels(const struct audio_stream *stream)
|
||||
{
|
||||
/* TODO Here is the code we need when we support arbitrary channel counts
|
||||
* alsa_device_proxy * proxy = ((struct stream_in*)stream)->proxy;
|
||||
* unsigned channel_count = proxy_get_channel_count(proxy);
|
||||
* uint32_t channel_mask = audio_channel_in_mask_from_count(channel_count);
|
||||
* ALOGV("in_get_channels() = 0x%X count:%d", channel_mask, channel_count);
|
||||
* return channel_mask;
|
||||
*/
|
||||
/* TODO When AudioPolicyManager & AudioFlinger supports arbitrary channels
|
||||
rewrite this to return the ACTUAL channel format */
|
||||
return AUDIO_CHANNEL_IN_STEREO;
|
||||
const struct stream_in *in = (const struct stream_in*)stream;
|
||||
return audio_channel_in_mask_from_count(in->hal_channel_count);
|
||||
}
|
||||
|
||||
static audio_format_t in_get_format(const struct audio_stream *stream)
|
||||
|
@ -808,7 +798,7 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t byte
|
|||
*/
|
||||
num_read_buff_bytes = bytes;
|
||||
int num_device_channels = proxy_get_channel_count(&in->proxy);
|
||||
int num_req_channels = 2; /* always, for now */
|
||||
int num_req_channels = in->hal_channel_count;
|
||||
|
||||
if (num_device_channels != num_req_channels) {
|
||||
num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
|
||||
|
@ -960,19 +950,18 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
|
|||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (config->channel_mask == AUDIO_CHANNEL_NONE) {
|
||||
/* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input
|
||||
* formats */
|
||||
config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
|
||||
|
||||
} else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
|
||||
/* allow only stereo capture for now */
|
||||
config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
|
||||
ret = -EINVAL;
|
||||
/* Channels */
|
||||
unsigned proposed_channel_count = profile_get_default_channel_count(in->profile);
|
||||
if (k_force_channels) {
|
||||
proposed_channel_count = k_force_channels;
|
||||
} else if (config->channel_mask != AUDIO_CHANNEL_NONE) {
|
||||
proposed_channel_count = audio_channel_count_from_in_mask(config->channel_mask);
|
||||
}
|
||||
// proxy_config.channels = 0; /* don't change */
|
||||
proxy_config.channels = profile_get_default_channel_count(in->profile);
|
||||
|
||||
/* we can expose any channel count mask, and emulate internally. */
|
||||
config->channel_mask = audio_channel_in_mask_from_count(proposed_channel_count);
|
||||
in->hal_channel_count = proposed_channel_count;
|
||||
proxy_config.channels = profile_get_default_channel_count(in->profile);
|
||||
proxy_prepare(&in->proxy, in->profile, &proxy_config);
|
||||
|
||||
in->standby = true;
|
||||
|
|
Loading…
Reference in a new issue