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

Commit eafe1812 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "hal: Add support for compressed capture"

parents f9a9dfe6 e62d784d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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 \
+20 −0
Original line number Diff line number Diff line
@@ -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 */
+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 */
+15 −4
Original line number Diff line number Diff line
@@ -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",
@@ -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 */
@@ -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:
@@ -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);
}
@@ -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);
    }
@@ -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__);
@@ -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);
@@ -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;
}

+1 −0
Original line number Diff line number Diff line
@@ -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