Loading hal/Android.mk +5 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,11 @@ ifdef MULTIPLE_HW_VARIANTS_ENABLED LOCAL_SRC_FILES += $(AUDIO_PLATFORM)/hw_info.c endif ifneq ($(strip $(AUDIO_FEATURE_DISABLED_COMPRESS_CAPTURE)),true) LOCAL_CFLAGS += -DCOMPRESS_CAPTURE_ENABLED LOCAL_SRC_FILES += audio_extn/compress_capture.c endif LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils \ Loading hal/audio_extn/audio_extn.h +20 −0 Original line number Diff line number Diff line Loading @@ -137,4 +137,24 @@ void audio_extn_spkr_prot_stop_processing(); bool audio_extn_spkr_prot_is_enabled(); #endif #ifndef COMPRESS_CAPTURE_ENABLED #define audio_extn_compr_cap_init(adev,in) (0) #define audio_extn_compr_cap_enabled() (0) #define audio_extn_compr_cap_format_supported(format) (0) #define audio_extn_compr_cap_usecase_supported(usecase) (0) #define audio_extn_compr_cap_get_buffer_size(format) (0) #define audio_extn_compr_cap_read(in, buffer, bytes) (0) #define audio_extn_compr_cap_deinit() (0) #else void audio_extn_compr_cap_init(struct audio_device *adev, struct stream_in *in); bool audio_extn_compr_cap_enabled(); bool audio_extn_compr_cap_format_supported(audio_format_t format); bool audio_extn_compr_cap_usecase_supported(audio_usecase_t usecase); size_t audio_extn_compr_cap_get_buffer_size(audio_format_t format); size_t audio_extn_compr_cap_read(struct stream_in *in, void *buffer, size_t bytes); void audio_extn_compr_cap_deinit(); #endif #endif /* AUDIO_EXTN_H */ hal/audio_extn/compress_capture.c 0 → 100644 +153 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "audio_hw_compress" /*#define LOG_NDEBUG 0*/ #define LOG_NDDEBUG 0 #include <errno.h> #include <cutils/properties.h> #include <stdlib.h> #include <dlfcn.h> #include <cutils/str_parms.h> #include <cutils/log.h> #include "audio_hw.h" #include "platform.h" #include "platform_api.h" #include "sound/compress_params.h" #include "sound/compress_offload.h" #ifdef COMPRESS_CAPTURE_ENABLED #define COMPRESS_IN_CONFIG_CHANNELS 1 #define COMPRESS_IN_CONFIG_PERIOD_SIZE 2048 #define COMPRESS_IN_CONFIG_PERIOD_COUNT 16 struct compress_in_module { uint8_t *in_buf; }; static struct compress_in_module c_in_mod = { .in_buf = NULL, }; void audio_extn_compr_cap_init(struct audio_device *adev, struct stream_in *in) { in->usecase = USECASE_AUDIO_RECORD_COMPRESS; in->config.channels = COMPRESS_IN_CONFIG_CHANNELS; in->config.period_size = COMPRESS_IN_CONFIG_PERIOD_SIZE; in->config.period_count= COMPRESS_IN_CONFIG_PERIOD_COUNT; in->config.format = AUDIO_FORMAT_AMR_WB; c_in_mod.in_buf = (uint8_t*)calloc(1, in->config.period_size*2); } void audio_extn_compr_cap_deinit() { if (c_in_mod.in_buf) { free(c_in_mod.in_buf); c_in_mod.in_buf = NULL; } } bool audio_extn_compr_cap_enabled() { char prop_value[PROPERTY_VALUE_MAX] = {0}; bool tunnel_encode = false; property_get("tunnel.audio.encode",prop_value,"0"); if (!strncmp("true", prop_value, sizeof("true"))) return true; else return false; } bool audio_extn_compr_cap_format_supported(audio_format_t format) { if (format == AUDIO_FORMAT_AMR_WB) return true; else return false; } bool audio_extn_compr_cap_usecase_supported(audio_usecase_t usecase) { if (usecase == USECASE_AUDIO_RECORD_COMPRESS) return true; else return false; } size_t audio_extn_compr_cap_get_buffer_size(audio_format_t format) { if (format == AUDIO_FORMAT_AMR_WB) /*One AMR WB frame is 61 bytes. Return that to the caller. The buffer size is not altered, that is still period size.*/ return AMR_WB_FRAMESIZE; else return 0; } size_t audio_extn_compr_cap_read(struct stream_in * in, void *buffer, size_t bytes) { int ret; struct snd_compr_audio_info *header; uint32_t c_in_header; uint32_t c_in_buf_size; c_in_buf_size = in->config.period_size*2; if (in->pcm) { ret = pcm_read(in->pcm, c_in_mod.in_buf, c_in_buf_size); if (ret < 0) { ALOGE("pcm_read() returned failure: %d", ret); return ret; } else { header = (struct snd_compr_audio_info *) c_in_mod.in_buf; c_in_header = sizeof(*header) + header->reserved[0]; if (header->frame_size > 0) { if (c_in_header + header->frame_size > c_in_buf_size) { ALOGW("AMR WB read buffer overflow."); header->frame_size = bytes - sizeof(*header) - header->reserved[0]; } ALOGV("c_in_buf: %p, data offset: %p, header size: %u," "reserved[0]: %u frame_size: %d", c_in_mod.in_buf, c_in_mod.in_buf + c_in_header, sizeof(*header), header->reserved[0], header->frame_size); memcpy(buffer, c_in_mod.in_buf + c_in_header, header->frame_size); } else { ALOGE("pcm_read() with zero frame size"); ret = -EINVAL; } } } return 0; } #endif /* COMPRESS_CAPTURE_ENABLED end */ hal/audio_hw.c +15 −4 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", [USECASE_AUDIO_RECORD] = "audio-record", [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress", [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record", [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record", [USECASE_AUDIO_PLAYBACK_FM] = "play-fm", Loading Loading @@ -741,7 +742,7 @@ int start_input_stream(struct stream_in *in) struct audio_usecase *uc_info; struct audio_device *adev = in->dev; in->usecase = platform_get_usecase_from_source(in->source); in->usecase = platform_update_usecase_from_source(in->source,in->usecase); ALOGV("%s: enter: usecase(%d)", __func__, in->usecase); /* Check if source matches incall recording usecase criteria */ Loading Loading @@ -1126,7 +1127,8 @@ static int check_input_parameters(uint32_t sample_rate, int ret = 0; if ((format != AUDIO_FORMAT_PCM_16_BIT) && !voice_extn_compress_voip_is_format_supported(format)) ret = -EINVAL; !voice_extn_compress_voip_is_format_supported(format) && !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL; switch (channel_count) { case 1: Loading Loading @@ -1714,6 +1716,8 @@ static size_t in_get_buffer_size(const struct audio_stream *stream) if(in->usecase == USECASE_COMPRESS_VOIP_CALL) return voice_extn_compress_voip_in_get_buffer_size(in); else if(audio_extn_compr_cap_usecase_supported(in->usecase)) return audio_extn_compr_cap_get_buffer_size(in->config.format); return in->config.period_size * audio_stream_frame_size(stream); } Loading Loading @@ -1865,6 +1869,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, if (in->pcm) { if (audio_extn_ssr_get_enabled() && popcount(in->channel_mask) == 6) ret = audio_extn_ssr_read(stream, buffer, bytes); else if (audio_extn_compr_cap_usecase_supported(in->usecase)) ret = audio_extn_compr_cap_read(in, buffer, bytes); else ret = pcm_read(in->pcm, buffer, bytes); } Loading Loading @@ -2383,8 +2389,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, __func__, ret); goto err_open; } } if (channel_count == 6) { } else if (channel_count == 6) { if(audio_extn_ssr_get_enabled()) { if(audio_extn_ssr_init(adev, in)) { ALOGE("%s: audio_extn_ssr_init failed", __func__); Loading @@ -2395,6 +2400,9 @@ static int adev_open_input_stream(struct audio_hw_device *dev, ret = -EINVAL; goto err_open; } } else if (audio_extn_compr_cap_enabled() && audio_extn_compr_cap_format_supported(config->format)) { audio_extn_compr_cap_init(adev, in); } else { in->config.channels = channel_count; frame_size = audio_stream_frame_size((struct audio_stream *)in); Loading Loading @@ -2434,6 +2442,9 @@ static void adev_close_input_stream(struct audio_hw_device *dev, } free(stream); if(audio_extn_compr_cap_enabled() && audio_extn_compr_cap_format_supported(in->config.format)) audio_extn_compr_cap_deinit(); return; } Loading hal/audio_hw.h +1 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ typedef enum { /* Capture usecases */ USECASE_AUDIO_RECORD, USECASE_AUDIO_RECORD_COMPRESS, USECASE_AUDIO_RECORD_LOW_LATENCY, USECASE_AUDIO_RECORD_FM_VIRTUAL, Loading Loading
hal/Android.mk +5 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,11 @@ ifdef MULTIPLE_HW_VARIANTS_ENABLED LOCAL_SRC_FILES += $(AUDIO_PLATFORM)/hw_info.c endif ifneq ($(strip $(AUDIO_FEATURE_DISABLED_COMPRESS_CAPTURE)),true) LOCAL_CFLAGS += -DCOMPRESS_CAPTURE_ENABLED LOCAL_SRC_FILES += audio_extn/compress_capture.c endif LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils \ Loading
hal/audio_extn/audio_extn.h +20 −0 Original line number Diff line number Diff line Loading @@ -137,4 +137,24 @@ void audio_extn_spkr_prot_stop_processing(); bool audio_extn_spkr_prot_is_enabled(); #endif #ifndef COMPRESS_CAPTURE_ENABLED #define audio_extn_compr_cap_init(adev,in) (0) #define audio_extn_compr_cap_enabled() (0) #define audio_extn_compr_cap_format_supported(format) (0) #define audio_extn_compr_cap_usecase_supported(usecase) (0) #define audio_extn_compr_cap_get_buffer_size(format) (0) #define audio_extn_compr_cap_read(in, buffer, bytes) (0) #define audio_extn_compr_cap_deinit() (0) #else void audio_extn_compr_cap_init(struct audio_device *adev, struct stream_in *in); bool audio_extn_compr_cap_enabled(); bool audio_extn_compr_cap_format_supported(audio_format_t format); bool audio_extn_compr_cap_usecase_supported(audio_usecase_t usecase); size_t audio_extn_compr_cap_get_buffer_size(audio_format_t format); size_t audio_extn_compr_cap_read(struct stream_in *in, void *buffer, size_t bytes); void audio_extn_compr_cap_deinit(); #endif #endif /* AUDIO_EXTN_H */
hal/audio_extn/compress_capture.c 0 → 100644 +153 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "audio_hw_compress" /*#define LOG_NDEBUG 0*/ #define LOG_NDDEBUG 0 #include <errno.h> #include <cutils/properties.h> #include <stdlib.h> #include <dlfcn.h> #include <cutils/str_parms.h> #include <cutils/log.h> #include "audio_hw.h" #include "platform.h" #include "platform_api.h" #include "sound/compress_params.h" #include "sound/compress_offload.h" #ifdef COMPRESS_CAPTURE_ENABLED #define COMPRESS_IN_CONFIG_CHANNELS 1 #define COMPRESS_IN_CONFIG_PERIOD_SIZE 2048 #define COMPRESS_IN_CONFIG_PERIOD_COUNT 16 struct compress_in_module { uint8_t *in_buf; }; static struct compress_in_module c_in_mod = { .in_buf = NULL, }; void audio_extn_compr_cap_init(struct audio_device *adev, struct stream_in *in) { in->usecase = USECASE_AUDIO_RECORD_COMPRESS; in->config.channels = COMPRESS_IN_CONFIG_CHANNELS; in->config.period_size = COMPRESS_IN_CONFIG_PERIOD_SIZE; in->config.period_count= COMPRESS_IN_CONFIG_PERIOD_COUNT; in->config.format = AUDIO_FORMAT_AMR_WB; c_in_mod.in_buf = (uint8_t*)calloc(1, in->config.period_size*2); } void audio_extn_compr_cap_deinit() { if (c_in_mod.in_buf) { free(c_in_mod.in_buf); c_in_mod.in_buf = NULL; } } bool audio_extn_compr_cap_enabled() { char prop_value[PROPERTY_VALUE_MAX] = {0}; bool tunnel_encode = false; property_get("tunnel.audio.encode",prop_value,"0"); if (!strncmp("true", prop_value, sizeof("true"))) return true; else return false; } bool audio_extn_compr_cap_format_supported(audio_format_t format) { if (format == AUDIO_FORMAT_AMR_WB) return true; else return false; } bool audio_extn_compr_cap_usecase_supported(audio_usecase_t usecase) { if (usecase == USECASE_AUDIO_RECORD_COMPRESS) return true; else return false; } size_t audio_extn_compr_cap_get_buffer_size(audio_format_t format) { if (format == AUDIO_FORMAT_AMR_WB) /*One AMR WB frame is 61 bytes. Return that to the caller. The buffer size is not altered, that is still period size.*/ return AMR_WB_FRAMESIZE; else return 0; } size_t audio_extn_compr_cap_read(struct stream_in * in, void *buffer, size_t bytes) { int ret; struct snd_compr_audio_info *header; uint32_t c_in_header; uint32_t c_in_buf_size; c_in_buf_size = in->config.period_size*2; if (in->pcm) { ret = pcm_read(in->pcm, c_in_mod.in_buf, c_in_buf_size); if (ret < 0) { ALOGE("pcm_read() returned failure: %d", ret); return ret; } else { header = (struct snd_compr_audio_info *) c_in_mod.in_buf; c_in_header = sizeof(*header) + header->reserved[0]; if (header->frame_size > 0) { if (c_in_header + header->frame_size > c_in_buf_size) { ALOGW("AMR WB read buffer overflow."); header->frame_size = bytes - sizeof(*header) - header->reserved[0]; } ALOGV("c_in_buf: %p, data offset: %p, header size: %u," "reserved[0]: %u frame_size: %d", c_in_mod.in_buf, c_in_mod.in_buf + c_in_header, sizeof(*header), header->reserved[0], header->frame_size); memcpy(buffer, c_in_mod.in_buf + c_in_header, header->frame_size); } else { ALOGE("pcm_read() with zero frame size"); ret = -EINVAL; } } } return 0; } #endif /* COMPRESS_CAPTURE_ENABLED end */
hal/audio_hw.c +15 −4 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", [USECASE_AUDIO_RECORD] = "audio-record", [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress", [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record", [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record", [USECASE_AUDIO_PLAYBACK_FM] = "play-fm", Loading Loading @@ -741,7 +742,7 @@ int start_input_stream(struct stream_in *in) struct audio_usecase *uc_info; struct audio_device *adev = in->dev; in->usecase = platform_get_usecase_from_source(in->source); in->usecase = platform_update_usecase_from_source(in->source,in->usecase); ALOGV("%s: enter: usecase(%d)", __func__, in->usecase); /* Check if source matches incall recording usecase criteria */ Loading Loading @@ -1126,7 +1127,8 @@ static int check_input_parameters(uint32_t sample_rate, int ret = 0; if ((format != AUDIO_FORMAT_PCM_16_BIT) && !voice_extn_compress_voip_is_format_supported(format)) ret = -EINVAL; !voice_extn_compress_voip_is_format_supported(format) && !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL; switch (channel_count) { case 1: Loading Loading @@ -1714,6 +1716,8 @@ static size_t in_get_buffer_size(const struct audio_stream *stream) if(in->usecase == USECASE_COMPRESS_VOIP_CALL) return voice_extn_compress_voip_in_get_buffer_size(in); else if(audio_extn_compr_cap_usecase_supported(in->usecase)) return audio_extn_compr_cap_get_buffer_size(in->config.format); return in->config.period_size * audio_stream_frame_size(stream); } Loading Loading @@ -1865,6 +1869,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, if (in->pcm) { if (audio_extn_ssr_get_enabled() && popcount(in->channel_mask) == 6) ret = audio_extn_ssr_read(stream, buffer, bytes); else if (audio_extn_compr_cap_usecase_supported(in->usecase)) ret = audio_extn_compr_cap_read(in, buffer, bytes); else ret = pcm_read(in->pcm, buffer, bytes); } Loading Loading @@ -2383,8 +2389,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, __func__, ret); goto err_open; } } if (channel_count == 6) { } else if (channel_count == 6) { if(audio_extn_ssr_get_enabled()) { if(audio_extn_ssr_init(adev, in)) { ALOGE("%s: audio_extn_ssr_init failed", __func__); Loading @@ -2395,6 +2400,9 @@ static int adev_open_input_stream(struct audio_hw_device *dev, ret = -EINVAL; goto err_open; } } else if (audio_extn_compr_cap_enabled() && audio_extn_compr_cap_format_supported(config->format)) { audio_extn_compr_cap_init(adev, in); } else { in->config.channels = channel_count; frame_size = audio_stream_frame_size((struct audio_stream *)in); Loading Loading @@ -2434,6 +2442,9 @@ static void adev_close_input_stream(struct audio_hw_device *dev, } free(stream); if(audio_extn_compr_cap_enabled() && audio_extn_compr_cap_format_supported(in->config.format)) audio_extn_compr_cap_deinit(); return; } Loading
hal/audio_hw.h +1 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ typedef enum { /* Capture usecases */ USECASE_AUDIO_RECORD, USECASE_AUDIO_RECORD_COMPRESS, USECASE_AUDIO_RECORD_LOW_LATENCY, USECASE_AUDIO_RECORD_FM_VIRTUAL, Loading