Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9098999b authored by Ravi Kumar Alamanda's avatar Ravi Kumar Alamanda Committed by Steve Kondik
Browse files

hal: add support for low-latency capture

- add support for low-latency capture

Change-Id: Ic8a82854799adfa4eb1fcd323e0177eeadc7e319
parent f37cbc13
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -161,6 +161,10 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD)),true)
    LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED
endif

ifeq ($(string $(AUDIO_FEATURE_ENABLED_LOW_LATENCY_CAPTURE)),true)
    LOCAL_CFLAGS += -DLOW_LATENCY_CAPTURE_USE_CASE=1
endif

LOCAL_SHARED_LIBRARIES := \
	liblog \
	libcutils \
+76 −21
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
 */

#define LOG_TAG "audio_hw_primary"
/*#define LOG_NDEBUG 0*/
#define LOG_NDEBUG 0
/*#define VERY_VERY_VERBOSE_LOGGING*/
#ifdef VERY_VERY_VERBOSE_LOGGING
#define ALOGVV ALOGV
@@ -69,6 +69,9 @@
#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
#endif

static unsigned int configured_low_latency_capture_period_size =
        LOW_LATENCY_CAPTURE_PERIOD_SIZE;

struct pcm_config pcm_config_deep_buffer = {
    .channels = 2,
    .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
@@ -357,6 +360,19 @@ static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
    return 0;
}

int pcm_ioctl(struct pcm *pcm, int request, ...)
{
    va_list ap;
    void * arg;
    int pcm_fd = *(int*)pcm;

    va_start(ap, request);
    arg = va_arg(ap, void *);
    va_end(ap);

    return ioctl(pcm_fd, request, arg);
}

int enable_audio_route(struct audio_device *adev,
                       struct audio_usecase *usecase)
{
@@ -1474,7 +1490,8 @@ static int check_input_parameters(uint32_t sample_rate,

static size_t get_input_buffer_size(uint32_t sample_rate,
                                    audio_format_t format,
                                    int channel_count)
                                    int channel_count,
                                    bool is_low_latency)
{
    size_t size = 0;

@@ -1482,13 +1499,19 @@ static size_t get_input_buffer_size(uint32_t sample_rate,
        return 0;

    size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
    if (is_low_latency)
        size = configured_low_latency_capture_period_size;
    /* ToDo: should use frame_size computed based on the format and
       channel_count here. */
    size *= sizeof(short) * channel_count;

    /* make sure the size is multiple of 64 */
    size += 0x3f;
    size &= ~0x3f;
    /* make sure the size is multiple of 32 bytes
     * At 48 kHz mono 16-bit PCM:
     *  5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
     *  3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
     */
    size += 0x1f;
    size &= ~0x1f;

    return size;
}
@@ -3065,7 +3088,8 @@ static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unu
{
    int channel_count = audio_channel_count_from_in_mask(config->channel_mask);

    return get_input_buffer_size(config->sample_rate, config->format, channel_count);
    return get_input_buffer_size(config->sample_rate, config->format, channel_count,
            false /* is_low_latency: since we don't know, be conservative */);
}

static int adev_open_input_stream(struct audio_hw_device *dev,
@@ -3081,7 +3105,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
    struct stream_in *in;
    int ret = 0, buffer_size, frame_size;
    int channel_count = audio_channel_count_from_in_mask(config->channel_mask);

    bool is_low_latency = false;

    *stream_in = NULL;
    if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
@@ -3124,6 +3148,13 @@ static int adev_open_input_stream(struct audio_hw_device *dev,

    /* Update config params with the requested sample rate and channels */
    in->usecase = USECASE_AUDIO_RECORD;
    if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
            (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
        is_low_latency = true;
#if LOW_LATENCY_CAPTURE_USE_CASE
        in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
#endif
    }
    in->config = pcm_config_audio_capture;
    in->config.rate = config->sample_rate;
    in->format = config->format;
@@ -3167,7 +3198,8 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
        frame_size = audio_stream_in_frame_size(&in->stream);
        buffer_size = get_input_buffer_size(config->sample_rate,
                                            config->format,
                                            channel_count);
                                            channel_count,
                                            is_low_latency);
        in->config.period_size = buffer_size / frame_size;
    }

@@ -3239,6 +3271,23 @@ static int adev_close(hw_device_t *device)
    return 0;
}

/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
 * or 0 otherwise.  A return value of 1 doesn't mean the value is guaranteed to work,
 * just that it _might_ work.
 */
static int period_size_is_plausible_for_low_latency(int period_size)
{
    switch (period_size) {
    case 160:
    case 240:
    case 320:
    case 480:
        return 1;
    default:
        return 0;
    }
}

static int adev_open(const hw_module_t *module, const char *name,
                     hw_device_t **device)
{
@@ -3357,23 +3406,29 @@ static int adev_open(const hw_module_t *module, const char *name,
    *device = &adev->device.common;

    audio_device_ref_count++;
    pthread_mutex_unlock(&adev_init_lock);

    ALOGV("%s: exit", __func__);
    return 0;
    char value[PROPERTY_VALUE_MAX];
    int trial;
    if (property_get("audio_hal.period_size", value, NULL) > 0) {
        trial = atoi(value);
        if (period_size_is_plausible_for_low_latency(trial)) {
            pcm_config_low_latency.period_size = trial;
            pcm_config_low_latency.start_threshold = trial / 4;
            pcm_config_low_latency.avail_min = trial / 4;
            configured_low_latency_capture_period_size = trial;
        }
    }
    if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
        trial = atoi(value);
        if (period_size_is_plausible_for_low_latency(trial)) {
            configured_low_latency_capture_period_size = trial;
        }
    }

int pcm_ioctl(struct pcm *pcm, int request, ...)
{
    va_list ap;
    void * arg;
    int pcm_fd = *(int*)pcm;

    va_start(ap, request);
    arg = va_arg(ap, void *);
    va_end(ap);
    pthread_mutex_unlock(&adev_init_lock);

    return ioctl(pcm_fd, request, arg);
    ALOGV("%s: exit", __func__);
    return 0;
}

static struct hw_module_methods_t hal_module_methods = {
+3 −0
Original line number Diff line number Diff line
@@ -121,4 +121,7 @@ enum {
#define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
#define AFE_PROXY_RECORD_PCM_DEVICE 8

#define LOW_LATENCY_CAPTURE_SAMPLE_RATE 48000
#define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240

#endif // QCOM_AUDIO_PLATFORM_H
+3 −0
Original line number Diff line number Diff line
@@ -167,6 +167,9 @@ enum {
#define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20
#define AUDIO_CAPTURE_PERIOD_COUNT 2

#define LOW_LATENCY_CAPTURE_SAMPLE_RATE 48000
#define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240

#define DEVICE_NAME_MAX_SIZE 128
#define HW_INFO_ARRAY_MAX_SIZE 32